summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llcharacter/llvisualparam.cpp10
-rw-r--r--indra/llcharacter/llvisualparam.h6
-rw-r--r--indra/llplugin/llpluginclassmedia.cpp30
-rw-r--r--indra/llplugin/llpluginclassmedia.h1
-rw-r--r--indra/llplugin/llpluginclassmediaowner.h3
-rw-r--r--indra/llui/lllineeditor.cpp25
-rw-r--r--indra/llui/lltabcontainer.cpp37
-rw-r--r--indra/llui/lltabcontainer.h3
-rw-r--r--indra/llui/lltextbase.cpp102
-rw-r--r--indra/llui/lltextbase.h18
-rw-r--r--indra/llui/lltexteditor.cpp11
-rw-r--r--indra/llui/lltexteditor.h2
-rw-r--r--indra/media_plugins/base/media_plugin_base.cpp1
-rw-r--r--indra/media_plugins/base/media_plugin_base.h1
-rw-r--r--indra/media_plugins/quicktime/media_plugin_quicktime.cpp26
-rw-r--r--indra/media_plugins/webkit/media_plugin_webkit.cpp18
-rw-r--r--indra/newview/CMakeLists.txt90
-rw-r--r--indra/newview/app_settings/settings.xml44
-rw-r--r--indra/newview/character/avatar_lad.xml7
-rw-r--r--indra/newview/llagent.cpp8
-rw-r--r--indra/newview/llagentui.cpp5
-rw-r--r--indra/newview/llagentui.h5
-rw-r--r--indra/newview/llagentwearables.cpp11
-rw-r--r--indra/newview/llagentwearables.h2
-rw-r--r--indra/newview/llappviewer.cpp4
-rw-r--r--indra/newview/llavatariconctrl.h2
-rw-r--r--indra/newview/llavatarlist.cpp103
-rw-r--r--indra/newview/llavatarlist.h14
-rw-r--r--indra/newview/llavatarlistitem.cpp72
-rw-r--r--indra/newview/llavatarlistitem.h10
-rw-r--r--indra/newview/llchannelmanager.cpp4
-rw-r--r--indra/newview/llchathistory.cpp281
-rw-r--r--indra/newview/llchathistory.h11
-rw-r--r--indra/newview/llchiclet.cpp3
-rw-r--r--indra/newview/lldriverparam.cpp1
-rw-r--r--indra/newview/llfavoritesbar.cpp32
-rw-r--r--indra/newview/llfavoritesbar.h2
-rw-r--r--indra/newview/llfloaterabout.cpp265
-rw-r--r--indra/newview/llfloaterchat.cpp13
-rw-r--r--indra/newview/llfloaterchat.h2
-rw-r--r--indra/newview/llfloaterchatterbox.cpp2
-rw-r--r--indra/newview/llfloaterinventory.cpp6
-rw-r--r--indra/newview/llfloaterpreference.cpp17
-rw-r--r--indra/newview/llfloatervoicedevicesettings.cpp2
-rw-r--r--indra/newview/llimfloater.cpp242
-rw-r--r--indra/newview/llimfloater.h20
-rw-r--r--indra/newview/llimpanel.cpp937
-rw-r--r--indra/newview/llimpanel.h137
-rw-r--r--indra/newview/llimview.cpp362
-rw-r--r--indra/newview/llimview.h95
-rw-r--r--indra/newview/llinventorybridge.cpp264
-rw-r--r--indra/newview/llinventorymodel.cpp8
-rw-r--r--indra/newview/lllandmarkactions.cpp2
-rw-r--r--indra/newview/lllandmarkactions.h2
-rw-r--r--indra/newview/lllogchat.cpp60
-rw-r--r--indra/newview/lllogchat.h11
-rw-r--r--indra/newview/llmoveview.cpp8
-rw-r--r--indra/newview/llmutelist.cpp1
-rw-r--r--indra/newview/llnavigationbar.cpp31
-rw-r--r--indra/newview/llnavigationbar.h14
-rw-r--r--indra/newview/llnearbychat.cpp20
-rw-r--r--indra/newview/llnearbychatbar.cpp26
-rw-r--r--indra/newview/llnearbychatbar.h5
-rw-r--r--indra/newview/llnotificationtiphandler.cpp22
-rw-r--r--indra/newview/llpanelimcontrolpanel.cpp94
-rw-r--r--indra/newview/llpanelimcontrolpanel.h34
-rw-r--r--indra/newview/llpanellandmarks.cpp157
-rw-r--r--indra/newview/llpanellandmarks.h22
-rw-r--r--indra/newview/llpanelpeople.cpp34
-rw-r--r--indra/newview/llpanelplaceinfo.cpp66
-rw-r--r--indra/newview/llpanelplaceinfo.h8
-rw-r--r--indra/newview/llpanelplaces.cpp11
-rw-r--r--indra/newview/llpanelprimmediacontrols.cpp1103
-rw-r--r--indra/newview/llpanelprimmediacontrols.h148
-rw-r--r--indra/newview/llparticipantlist.cpp22
-rw-r--r--indra/newview/llscreenchannel.cpp29
-rw-r--r--indra/newview/llspeakers.cpp639
-rw-r--r--indra/newview/llspeakers.h172
-rw-r--r--indra/newview/llsyswellwindow.cpp6
-rw-r--r--indra/newview/llsyswellwindow.h1
-rw-r--r--indra/newview/lltexlayer.cpp3
-rw-r--r--indra/newview/lltexlayerparams.cpp17
-rw-r--r--indra/newview/lltexlayerparams.h1
-rw-r--r--indra/newview/lltoast.cpp18
-rw-r--r--indra/newview/lltoast.h3
-rw-r--r--indra/newview/lltoastimpanel.cpp1
-rw-r--r--indra/newview/lltoolpie.cpp3
-rw-r--r--indra/newview/llviewercontrol.cpp25
-rw-r--r--indra/newview/llviewercontrol.h3
-rw-r--r--indra/newview/llviewerinventory.cpp1
-rw-r--r--indra/newview/llviewermedia.cpp183
-rw-r--r--indra/newview/llviewermedia.h11
-rw-r--r--indra/newview/llviewermediafocus.cpp42
-rw-r--r--indra/newview/llviewermediafocus.h4
-rw-r--r--indra/newview/llviewermenu.cpp1
-rw-r--r--indra/newview/llviewermessage.cpp4
-rw-r--r--indra/newview/llviewertexteditor.cpp56
-rw-r--r--indra/newview/llviewerwindow.cpp19
-rw-r--r--indra/newview/llvoavatar.cpp52
-rw-r--r--indra/newview/llvoavatar.h5
-rw-r--r--indra/newview/llvoavatarself.cpp40
-rw-r--r--indra/newview/llvoavatarself.h2
-rw-r--r--indra/newview/llvoicechannel.cpp872
-rw-r--r--indra/newview/llvoicechannel.h168
-rw-r--r--indra/newview/llvoiceclient.cpp2
-rw-r--r--indra/newview/llwearable.cpp33
-rw-r--r--indra/newview/llwearable.h1
-rw-r--r--indra/newview/skins/default/textures/map_avatar_8.tgabin300 -> 300 bytes
-rw-r--r--indra/newview/skins/default/textures/textures.xml141
-rw-r--r--indra/newview/skins/default/xui/en/floater_about.xml104
-rw-r--r--indra/newview/skins/default/xui/en/floater_about_land.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_camera.xml109
-rw-r--r--indra/newview/skins/default/xui/en/floater_nearby_chat.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_pay.xml7
-rw-r--r--indra/newview/skins/default/xui/en/floater_preferences.xml25
-rw-r--r--indra/newview/skins/default/xui/en/floater_preview_notecard.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_report_abuse.xml102
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_textbox.xml67
-rw-r--r--indra/newview/skins/default/xui/en/menu_object_icon.xml27
-rw-r--r--indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml11
-rw-r--r--indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml11
-rw-r--r--indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml11
-rw-r--r--indra/newview/skins/default/xui/en/menu_place_add_button.xml27
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml11
-rw-r--r--indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml29
-rw-r--r--indra/newview/skins/default/xui/en/panel_avatar_list_item.xml11
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_control_panel.xml12
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_roles.xml4
-rw-r--r--indra/newview/skins/default/xui/en/panel_im_control_panel.xml9
-rw-r--r--indra/newview/skins/default/xui/en/panel_instant_message.xml43
-rw-r--r--indra/newview/skins/default/xui/en/panel_landmarks.xml14
-rw-r--r--indra/newview/skins/default/xui/en/panel_notification.xml59
-rw-r--r--indra/newview/skins/default/xui/en/panel_people.xml3
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_advanced.xml105
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_sound.xml426
-rw-r--r--indra/newview/skins/default/xui/en/panel_prim_media_controls.xml594
-rw-r--r--indra/newview/skins/default/xui/en/panel_toast.xml43
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml26
-rw-r--r--indra/newview/skins/default/xui/en/widgets/chat_history.xml4
-rw-r--r--indra/newview/skins/default/xui/en/widgets/gesture_combo_box.xml3
-rw-r--r--indra/newview/skins/default/xui/en/widgets/tab_container.xml1
141 files changed, 6948 insertions, 2792 deletions
diff --git a/indra/llcharacter/llvisualparam.cpp b/indra/llcharacter/llvisualparam.cpp
index 9e4957342c..6232c7588b 100644
--- a/indra/llcharacter/llvisualparam.cpp
+++ b/indra/llcharacter/llvisualparam.cpp
@@ -173,7 +173,8 @@ LLVisualParam::LLVisualParam()
mTargetWeight( 0.f ),
mIsAnimating( FALSE ),
mID( -1 ),
- mInfo( 0 )
+ mInfo( 0 ),
+ mIsDummy(FALSE)
{
}
@@ -251,6 +252,13 @@ void LLVisualParam::setWeight(F32 weight, BOOL set_by_user)
//-----------------------------------------------------------------------------
void LLVisualParam::setAnimationTarget(F32 target_value, BOOL set_by_user)
{
+ // don't animate dummy parameters
+ if (mIsDummy)
+ {
+ setWeight(target_value, set_by_user);
+ return;
+ }
+
if (mInfo)
{
if (getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE)
diff --git a/indra/llcharacter/llvisualparam.h b/indra/llcharacter/llvisualparam.h
index 0b516b9374..affc49debf 100644
--- a/indra/llcharacter/llvisualparam.h
+++ b/indra/llcharacter/llvisualparam.h
@@ -148,15 +148,19 @@ public:
LLVisualParam* getNextParam() { return mNext; }
void setNextParam( LLVisualParam *next );
- virtual void setAnimating(BOOL is_animating) { mIsAnimating = is_animating; }
+ virtual void setAnimating(BOOL is_animating) { mIsAnimating = is_animating && !mIsDummy; }
BOOL getAnimating() const { return mIsAnimating; }
+ void setIsDummy(BOOL is_self) { mIsDummy = is_self; }
+
protected:
F32 mCurWeight; // current weight
F32 mLastWeight; // last weight
LLVisualParam* mNext; // next param in a shared chain
F32 mTargetWeight; // interpolation target
BOOL mIsAnimating; // this value has been given an interpolation target
+ BOOL mIsDummy; // this is used to prevent dummy visual params from animating
+
S32 mID; // id for storing weight/morphtarget compares compactly
LLVisualParamInfo *mInfo;
diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp
index 26802bbd1c..457c074ef1 100644
--- a/indra/llplugin/llpluginclassmedia.cpp
+++ b/indra/llplugin/llpluginclassmedia.cpp
@@ -552,6 +552,23 @@ void LLPluginClassMedia::loadURI(const std::string &uri)
sendMessage(message);
}
+const char* LLPluginClassMedia::priorityToString(EPriority priority)
+{
+ const char* result = "UNKNOWN";
+ switch(priority)
+ {
+ case PRIORITY_UNLOADED: result = "unloaded"; break;
+ case PRIORITY_STOPPED: result = "stopped"; break;
+ case PRIORITY_HIDDEN: result = "hidden"; break;
+ case PRIORITY_SLIDESHOW: result = "slideshow"; break;
+ case PRIORITY_LOW: result = "low"; break;
+ case PRIORITY_NORMAL: result = "normal"; break;
+ case PRIORITY_HIGH: result = "high"; break;
+ }
+
+ return result;
+}
+
void LLPluginClassMedia::setPriority(EPriority priority)
{
if(mPriority != priority)
@@ -560,35 +577,28 @@ void LLPluginClassMedia::setPriority(EPriority priority)
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_priority");
- std::string priority_string;
+ std::string priority_string = priorityToString(priority);
switch(priority)
{
case PRIORITY_UNLOADED:
- priority_string = "unloaded";
mSleepTime = 1.0f;
break;
case PRIORITY_STOPPED:
- priority_string = "stopped";
mSleepTime = 1.0f;
break;
case PRIORITY_HIDDEN:
- priority_string = "hidden";
mSleepTime = 1.0f;
break;
case PRIORITY_SLIDESHOW:
- priority_string = "slideshow";
mSleepTime = 1.0f;
break;
case PRIORITY_LOW:
- priority_string = "low";
mSleepTime = 1.0f / 50.0f;
break;
case PRIORITY_NORMAL:
- priority_string = "normal";
mSleepTime = 1.0f / 100.0f;
break;
case PRIORITY_HIGH:
- priority_string = "high";
mSleepTime = 1.0f / 100.0f;
break;
}
@@ -794,6 +804,10 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
{
mStatus = LLPluginClassMediaOwner::MEDIA_PAUSED;
}
+ else if(status == "done")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_DONE;
+ }
else
{
// empty string or any unknown string
diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h
index 4f9763474e..90ecd1e073 100644
--- a/indra/llplugin/llpluginclassmedia.h
+++ b/indra/llplugin/llpluginclassmedia.h
@@ -150,6 +150,7 @@ public:
PRIORITY_HIGH // media has user focus and/or is taking up most of the screen
}EPriority;
+ static const char* priorityToString(EPriority priority);
void setPriority(EPriority priority);
void setLowPrioritySizeLimit(int size);
diff --git a/indra/llplugin/llpluginclassmediaowner.h b/indra/llplugin/llpluginclassmediaowner.h
index 4690f09172..c798af29ca 100644
--- a/indra/llplugin/llpluginclassmediaowner.h
+++ b/indra/llplugin/llpluginclassmediaowner.h
@@ -70,7 +70,8 @@ public:
MEDIA_ERROR, // navigation/preroll failed
MEDIA_PLAYING, // playing (only for time-based media)
MEDIA_PAUSED, // paused (only for time-based media)
-
+ MEDIA_DONE // finished playing (only for time-based media)
+
} EMediaStatus;
virtual ~LLPluginClassMediaOwner() {};
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index e053477d58..75905d0927 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -1544,18 +1544,24 @@ void LLLineEditor::drawBackground()
image = mBgImage;
}
+ F32 alpha = getDrawContext().mAlpha;
// optionally draw programmatic border
if (has_focus)
{
+ LLColor4 tmp_color = gFocusMgr.getFocusColor();
+ tmp_color.setAlpha(alpha);
image->drawBorder(0, 0, getRect().getWidth(), getRect().getHeight(),
- gFocusMgr.getFocusColor(),
+ tmp_color,
gFocusMgr.getFocusFlashWidth());
}
- image->draw(getLocalRect());
+ LLColor4 tmp_color = UI_VERTEX_COLOR;
+ tmp_color.setAlpha(alpha);
+ image->draw(getLocalRect(), tmp_color);
}
void LLLineEditor::draw()
{
+ F32 alpha = getDrawContext().mAlpha;
S32 text_len = mText.length();
static LLUICachedControl<S32> lineeditor_cursor_thickness ("UILineEditorCursorThickness", 0);
static LLUICachedControl<S32> lineeditor_v_pad ("UILineEditorVPad", 0);
@@ -1608,8 +1614,10 @@ void LLLineEditor::draw()
{
text_color = mReadOnlyFgColor.get();
}
+ text_color.setAlpha(alpha);
LLColor4 label_color = mTentativeFgColor.get();
-
+ label_color.setAlpha(alpha);
+
if (hasPreeditString())
{
// Draw preedit markers. This needs to be before drawing letters.
@@ -1632,7 +1640,7 @@ void LLLineEditor::draw()
preedit_pixels_right - preedit_standout_gap - 1,
background.mBottom + preedit_standout_position - preedit_standout_thickness,
(text_color * preedit_standout_brightness
- + mPreeditBgColor * (1 - preedit_standout_brightness)).setAlpha(1.0f));
+ + mPreeditBgColor * (1 - preedit_standout_brightness)).setAlpha(alpha/*1.0f*/));
}
else
{
@@ -1641,7 +1649,7 @@ void LLLineEditor::draw()
preedit_pixels_right - preedit_marker_gap - 1,
background.mBottom + preedit_marker_position - preedit_marker_thickness,
(text_color * preedit_marker_brightness
- + mPreeditBgColor * (1 - preedit_marker_brightness)).setAlpha(1.0f));
+ + mPreeditBgColor * (1 - preedit_marker_brightness)).setAlpha(alpha/*1.0f*/));
}
}
}
@@ -1684,15 +1692,17 @@ void LLLineEditor::draw()
if( (rendered_pixels_right < (F32)mMaxHPixels) && (rendered_text < text_len) )
{
LLColor4 color = mHighlightColor;
+ color.setAlpha(alpha);
// selected middle
S32 width = mGLFont->getWidth(mText.getWString().c_str(), mScrollHPos + rendered_text, select_right - mScrollHPos - rendered_text);
width = llmin(width, mMaxHPixels - llround(rendered_pixels_right));
gl_rect_2d(llround(rendered_pixels_right), cursor_top, llround(rendered_pixels_right)+width, cursor_bottom, color);
+ LLColor4 tmp_color( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], alpha );
rendered_text += mGLFont->render(
mText, mScrollHPos + rendered_text,
rendered_pixels_right, text_bottom,
- LLColor4( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], 1 ),
+ tmp_color,
LLFontGL::LEFT, LLFontGL::BOTTOM,
0,
LLFontGL::NO_SHADOW,
@@ -1758,8 +1768,9 @@ void LLLineEditor::draw()
cursor_right, cursor_bottom, text_color);
if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection())
{
+ LLColor4 tmp_color( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], alpha );
mGLFont->render(mText, getCursor(), (F32)(cursor_left + lineeditor_cursor_thickness / 2), text_bottom,
- LLColor4( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], 1 ),
+ tmp_color,
LLFontGL::LEFT, LLFontGL::BOTTOM,
0,
LLFontGL::NO_SHADOW,
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index 732c01614b..cde4c75518 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -44,6 +44,7 @@
#include "lluictrlfactory.h"
#include "llrender.h"
#include "llfloater.h"
+#include "lltrans.h"
//----------------------------------------------------------------------------
@@ -153,6 +154,8 @@ LLTabContainer::LLTabContainer(const LLTabContainer::Params& p)
mRightTabBtnOffset(p.tab_padding_right),
mTotalTabWidth(0),
mTabPosition(p.tab_position),
+ mFontHalign(p.font_halign),
+ mFont(p.font.isProvided() ? p.font() : (mIsVertical ? LLFontGL::getFontSansSerif() : LLFontGL::getFontSansSerifSmall())),
mFirstTabParams(p.first_tab),
mMiddleTabParams(p.middle_tab),
mLastTabParams(p.last_tab)
@@ -401,12 +404,6 @@ void LLTabContainer::draw()
}
}
}
- LLUI::pushMatrix();
- {
- LLUI::translate((F32)tuple->mButton->getRect().mLeft, (F32)tuple->mButton->getRect().mBottom, 0.f);
- tuple->mButton->draw();
- }
- LLUI::popMatrix();
idx++;
}
@@ -641,12 +638,6 @@ BOOL LLTabContainer::handleToolTip( S32 x, S32 y, MASK mask)
}
}
}
-
- for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
- {
- LLTabTuple* tuple = *iter;
- tuple->mButton->setVisible( FALSE );
- }
}
return handled;
}
@@ -836,8 +827,6 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
// already a child of mine
return;
}
- const LLFontGL* font =
- (mIsVertical ? LLFontGL::getFontSansSerif() : LLFontGL::getFontSansSerifSmall());
// Store the original label for possible xml export.
child->setLabel(label);
@@ -847,7 +836,7 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
S32 button_width = mMinTabWidth;
if (!mIsVertical)
{
- button_width = llclamp(font->getWidth(trimmed_label) + tab_padding, mMinTabWidth, mMaxTabWidth);
+ button_width = llclamp(mFont->getWidth(trimmed_label) + tab_padding, mMinTabWidth, mMaxTabWidth);
}
// Tab panel
@@ -934,7 +923,7 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
params.name(trimmed_label);
params.rect(btn_rect);
params.initial_value(trimmed_label);
- params.font(font);
+ params.font(mFont);
textbox = LLUICtrlFactory::create<LLTextBox> (params);
LLButton::Params p;
@@ -950,12 +939,12 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
p.rect(btn_rect);
p.follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT);
p.click_callback.function(boost::bind(&LLTabContainer::onTabBtn, this, _2, child));
- p.font(font);
+ p.font(mFont);
p.label(trimmed_label);
p.image_unselected(mMiddleTabParams.tab_left_image_unselected);
p.image_selected(mMiddleTabParams.tab_left_image_selected);
p.scale_image(true);
- p.font_halign = LLFontGL::LEFT;
+ p.font_halign = mFontHalign;
p.tab_stop(false);
if (indent)
{
@@ -965,18 +954,13 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
}
else
{
- std::string tooltip = trimmed_label;
- tooltip += "\nAlt-Left arrow for previous tab";
- tooltip += "\nAlt-Right arrow for next tab";
-
LLButton::Params p;
p.name(std::string(child->getName()) + " tab");
p.rect(btn_rect);
p.click_callback.function(boost::bind(&LLTabContainer::onTabBtn, this, _2, child));
- p.font(font);
+ p.font(mFont);
p.label(trimmed_label);
p.visible(false);
- p.tool_tip(tooltip);
p.scale_image(true);
p.image_unselected(tab_img);
p.image_selected(tab_selected_img);
@@ -984,7 +968,7 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
// Try to squeeze in a bit more text
p.pad_left(4);
p.pad_right(2);
- p.font_halign = LLFontGL::LEFT;
+ p.font_halign = mFontHalign;
p.follows.flags = FOLLOWS_LEFT;
p.follows.flags = FOLLOWS_LEFT;
@@ -1505,7 +1489,6 @@ void LLTabContainer::setTabImage(LLPanel* child, std::string image_name, const L
if (!mIsVertical)
{
- const LLFontGL* fontp = LLFontGL::getFontSansSerifSmall();
// remove current width from total tab strip width
mTotalTabWidth -= tuple->mButton->getRect().getWidth();
@@ -1516,7 +1499,7 @@ void LLTabContainer::setTabImage(LLPanel* child, std::string image_name, const L
tuple->mPadding = image_overlay_width;
tuple->mButton->setRightHPad(6);
- tuple->mButton->reshape(llclamp(fontp->getWidth(tuple->mButton->getLabelSelected()) + tab_padding + tuple->mPadding, mMinTabWidth, mMaxTabWidth),
+ tuple->mButton->reshape(llclamp(mFont->getWidth(tuple->mButton->getLabelSelected()) + tab_padding + tuple->mPadding, mMinTabWidth, mMaxTabWidth),
tuple->mButton->getRect().getHeight());
// add back in button width to total tab strip width
mTotalTabWidth += tuple->mButton->getRect().getWidth();
diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h
index a81974cd42..be9c6c7d06 100644
--- a/indra/llui/lltabcontainer.h
+++ b/indra/llui/lltabcontainer.h
@@ -262,6 +262,9 @@ private:
S32 mTabHeight;
LLFrameTimer mDragAndDropDelayTimer;
+
+ LLFontGL::HAlign mFontHalign;
+ const LLFontGL* mFont;
TabParams mFirstTabParams;
TabParams mMiddleTabParams;
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 0add3fb500..2b1d677ffb 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -419,9 +419,6 @@ void LLTextBase::drawCursor()
return;
}
- if (!mTextRect.contains(cursor_rect))
- return;
-
// Draw the cursor
// (Flash the cursor every half second starting a fixed time after the last keystroke)
F32 elapsed = mCursorBlinkTimer.getElapsedTimeF32();
@@ -973,7 +970,7 @@ void LLTextBase::draw()
: hasFocus()
? mFocusBgColor.get()
: mWriteableBgColor.get();
- gl_rect_2d(mDocumentView->getRect(), bg_color, TRUE);
+ gl_rect_2d(mTextRect, bg_color, TRUE);
}
// draw document view
@@ -1034,13 +1031,13 @@ S32 LLTextBase::getLeftOffset(S32 width)
switch (mHAlign)
{
case LLFontGL::LEFT:
- return 0;
+ return mHPad;
case LLFontGL::HCENTER:
- return (mTextRect.getWidth() - width) / 2;
+ return mHPad + (mTextRect.getWidth() - width - mHPad) / 2;
case LLFontGL::RIGHT:
return mTextRect.getWidth() - width;
default:
- return 0;
+ return mHPad;
}
}
@@ -1048,8 +1045,6 @@ S32 LLTextBase::getLeftOffset(S32 width)
static LLFastTimer::DeclareTimer FTM_TEXT_REFLOW ("Text Reflow");
void LLTextBase::reflow(S32 start_index)
{
- if (!mReflowNeeded) return;
-
LLFastTimer ft(FTM_TEXT_REFLOW);
updateSegments();
@@ -1078,7 +1073,7 @@ void LLTextBase::reflow(S32 start_index)
segment_set_t::iterator seg_iter = mSegments.begin();
S32 seg_offset = 0;
S32 line_start_index = 0;
- const S32 text_width = mTextRect.getWidth(); // optionally reserve room for margin
+ const S32 text_width = mTextRect.getWidth() - mHPad; // reserve room for margin
S32 remaining_pixels = text_width;
LLWString text(getWText());
S32 line_count = 0;
@@ -2037,7 +2032,6 @@ void LLTextBase::updateRects()
}
else
{
-
mContentsRect = mLineInfoList.begin()->mRect;
for (line_list_t::const_iterator line_iter = ++mLineInfoList.begin();
line_iter != mLineInfoList.end();
@@ -2046,13 +2040,28 @@ void LLTextBase::updateRects()
mContentsRect.unionWith(line_iter->mRect);
}
- mContentsRect.mRight += mHPad;
+ mContentsRect.mLeft = 0;
mContentsRect.mTop += mVPad;
- // get around rounding errors when clipping text against rectangle
- mContentsRect.stretch(1);
+
+ S32 delta_pos = -mContentsRect.mBottom;
+ // move line segments to fit new document rect
+ for (line_list_t::iterator it = mLineInfoList.begin(); it != mLineInfoList.end(); ++it)
+ {
+ it->mRect.translate(0, delta_pos);
+ }
+ mContentsRect.translate(0, delta_pos);
}
+ // update document container dimensions according to text contents
+ LLRect doc_rect = mContentsRect;
+ // use old mTextRect constraint document to width of viewable region
+ doc_rect.mRight = doc_rect.mLeft + mTextRect.getWidth();
+
+ mDocumentView->setShape(doc_rect);
+ //update mTextRect *after* mDocumentView has been resized
+ // so that scrollbars are added if document needs to scroll
+ // since mTextRect does not include scrollbars
LLRect old_text_rect = mTextRect;
mTextRect = mScroller ? mScroller->getContentWindowRect() : getLocalRect();
//FIXME: replace border with image?
@@ -2060,43 +2069,14 @@ void LLTextBase::updateRects()
{
mTextRect.stretch(-1);
}
- mTextRect.mLeft += mHPad;
- mTextRect.mTop -= mVPad;
if (mTextRect != old_text_rect)
{
needsReflow();
}
- // change document rect size too
- LLRect document_rect;
- if (mScroller)
- {
- // document is size of scroller or size of text contents, whichever is larger
- document_rect.setOriginAndSize(0, 0,
- mScroller->getContentWindowRect().getWidth(),
- llmax(mScroller->getContentWindowRect().getHeight(), mContentsRect.getHeight()));
- }
- else
- {
- // document size is just extents of reflowed text, reset to origin 0,0
- document_rect.set(0,
- getLocalRect().getHeight(),
- getLocalRect().getWidth(),
- llmin(0, getLocalRect().getHeight() - mContentsRect.getHeight()));
- }
- mDocumentView->setShape(document_rect);
-
- // after making document big enough to hold all the text, move the text to fit in the document
- if (!mLineInfoList.empty())
- {
- S32 delta_pos = mDocumentView->getRect().getHeight() - mLineInfoList.begin()->mRect.mTop - mVPad;
- // move line segments to fit new document rect
- for (line_list_t::iterator it = mLineInfoList.begin(); it != mLineInfoList.end(); ++it)
- {
- it->mRect.translate(0, delta_pos);
- }
- mContentsRect.translate(0, delta_pos);
- }
+ // update document container again, using new mTextRect
+ doc_rect.mRight = doc_rect.mLeft + mTextRect.getWidth();
+ mDocumentView->setShape(doc_rect);
}
@@ -2398,7 +2378,6 @@ S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin
{
if (text[last_char] == '\n')
{
- last_char++;
break;
}
}
@@ -2418,9 +2397,14 @@ S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin
// If at the beginning of a line, and a single character won't fit, draw it anyway
num_chars = 1;
}
- if (mStart + segment_offset + num_chars == mEditor.getLength())
+
+ // include *either* the EOF or newline character in this run of text
+ // but not both
+ S32 last_char_in_run = mStart + segment_offset + num_chars;
+ // check length first to avoid indexing off end of string
+ if (last_char_in_run >= mEditor.getLength()
+ || text[last_char_in_run] == '\n')
{
- // include terminating NULL
num_chars++;
}
return num_chars;
@@ -2442,12 +2426,14 @@ void LLNormalTextSegment::dump() const
// LLInlineViewSegment
//
-LLInlineViewSegment::LLInlineViewSegment(LLView* view, S32 start, S32 end, bool force_new_line, S32 hpad, S32 vpad)
+LLInlineViewSegment::LLInlineViewSegment(const Params& p, S32 start, S32 end)
: LLTextSegment(start, end),
- mView(view),
- mForceNewLine(force_new_line),
- mHPad(hpad), // one sided padding (applied to left and right)
- mVPad(vpad)
+ mView(p.view),
+ mForceNewLine(p.force_newline),
+ mLeftPad(p.left_pad),
+ mRightPad(p.right_pad),
+ mTopPad(p.top_pad),
+ mBottomPad(p.bottom_pad)
{
}
@@ -2467,8 +2453,8 @@ void LLInlineViewSegment::getDimensions(S32 first_char, S32 num_chars, S32& widt
}
else
{
- width = mHPad * 2 + mView->getRect().getWidth();
- height = mVPad * 2 + mView->getRect().getHeight();
+ width = mLeftPad + mRightPad + mView->getRect().getWidth();
+ height = mBottomPad + mTopPad + mView->getRect().getHeight();
}
}
@@ -2491,14 +2477,14 @@ S32 LLInlineViewSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin
void LLInlineViewSegment::updateLayout(const LLTextBase& editor)
{
LLRect start_rect = editor.getDocRectFromDocIndex(mStart);
- mView->setOrigin(start_rect.mLeft + mHPad, start_rect.mBottom + mVPad);
+ mView->setOrigin(start_rect.mLeft + mLeftPad, start_rect.mBottom + mBottomPad);
}
F32 LLInlineViewSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect)
{
// return padded width of widget
// widget is actually drawn during mDocumentView's draw()
- return (F32)(draw_rect.mLeft + mView->getRect().getWidth() + mHPad * 2);
+ return (F32)(draw_rect.mLeft + mView->getRect().getWidth() + mLeftPad + mRightPad);
}
void LLInlineViewSegment::unlinkFromDocument(LLTextBase* editor)
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index d0787f001e..14fd786127 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -459,7 +459,17 @@ public:
class LLInlineViewSegment : public LLTextSegment
{
public:
- LLInlineViewSegment(LLView* widget, S32 start, S32 end, bool force_new_line, S32 hpad = 0, S32 vpad = 0);
+ struct Params : public LLInitParam::Block<Params>
+ {
+ Mandatory<LLView*> view;
+ Optional<bool> force_newline;
+ Optional<S32> left_pad,
+ right_pad,
+ bottom_pad,
+ top_pad;
+ };
+
+ LLInlineViewSegment(const Params& p, S32 start, S32 end);
~LLInlineViewSegment();
/*virtual*/ void getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const;
/*virtual*/ S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const;
@@ -470,8 +480,10 @@ public:
/*virtual*/ void linkToDocument(class LLTextBase* editor);
private:
- S32 mHPad;
- S32 mVPad;
+ S32 mLeftPad;
+ S32 mRightPad;
+ S32 mTopPad;
+ S32 mBottomPad;
LLView* mView;
bool mForceNewLine;
};
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 570ca4b998..f0238dba49 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -2307,7 +2307,7 @@ void LLTextEditor::insertText(const std::string &new_text)
setEnabled( enabled );
}
-void LLTextEditor::appendWidget(LLView* widget, const std::string &widget_text, bool allow_undo, bool force_new_line, S32 hpad, S32 vpad)
+void LLTextEditor::appendWidget(const LLInlineViewSegment::Params& params, const std::string& text, bool allow_undo)
{
// Save old state
S32 selection_start = mSelectionStart;
@@ -2321,12 +2321,9 @@ void LLTextEditor::appendWidget(LLView* widget, const std::string &widget_text,
setCursorPos(old_length);
- LLWString widget_wide_text;
+ LLWString widget_wide_text = utf8str_to_wstring(text);
- // Add carriage return if not first line
- widget_wide_text = utf8str_to_wstring(widget_text);
-
- LLTextSegmentPtr segment = new LLInlineViewSegment(widget, old_length, old_length + widget_text.size(), force_new_line, hpad, vpad);
+ LLTextSegmentPtr segment = new LLInlineViewSegment(params, old_length, old_length + widget_wide_text.size());
insert(getLength(), widget_wide_text, FALSE, segment);
needsReflow();
@@ -2349,7 +2346,7 @@ void LLTextEditor::appendWidget(LLView* widget, const std::string &widget_text,
setCursorPos(cursor_pos);
}
- if( !allow_undo )
+ if (!allow_undo)
{
blockUndo();
}
diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h
index 4847f4d117..10fc94dedc 100644
--- a/indra/llui/lltexteditor.h
+++ b/indra/llui/lltexteditor.h
@@ -166,7 +166,7 @@ public:
// inserts text at cursor
void insertText(const std::string &text);
- void appendWidget(LLView* widget, const std::string &widget_text, bool allow_undo, bool force_newline, S32 hpad, S32 vpad);
+ void appendWidget(const LLInlineViewSegment::Params& params, const std::string& text, bool allow_undo);
// Non-undoable
void setText(const LLStringExplicit &utf8str);
diff --git a/indra/media_plugins/base/media_plugin_base.cpp b/indra/media_plugins/base/media_plugin_base.cpp
index 0b7092fad6..6acac07423 100644
--- a/indra/media_plugins/base/media_plugin_base.cpp
+++ b/indra/media_plugins/base/media_plugin_base.cpp
@@ -64,6 +64,7 @@ std::string MediaPluginBase::statusString()
case STATUS_ERROR: result = "error"; break;
case STATUS_PLAYING: result = "playing"; break;
case STATUS_PAUSED: result = "paused"; break;
+ case STATUS_DONE: result = "done"; break;
default:
// keep the empty string
break;
diff --git a/indra/media_plugins/base/media_plugin_base.h b/indra/media_plugins/base/media_plugin_base.h
index 8f600cb8d6..f1e96335f9 100644
--- a/indra/media_plugins/base/media_plugin_base.h
+++ b/indra/media_plugins/base/media_plugin_base.h
@@ -56,6 +56,7 @@ protected:
STATUS_ERROR,
STATUS_PLAYING,
STATUS_PAUSED,
+ STATUS_DONE
} EStatus;
class SharedSegmentInfo
diff --git a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
index c9ee1c8ac7..fb6d5b2905 100644
--- a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
+++ b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
@@ -420,7 +420,7 @@ private:
{
if ( mCommand == COMMAND_PLAY )
{
- if ( mStatus == STATUS_LOADED || mStatus == STATUS_PAUSED || mStatus == STATUS_PLAYING )
+ if ( mStatus == STATUS_LOADED || mStatus == STATUS_PAUSED || mStatus == STATUS_PLAYING || mStatus == STATUS_DONE )
{
long state = GetMovieLoadState( mMovieHandle );
@@ -446,7 +446,7 @@ private:
else
if ( mCommand == COMMAND_STOP )
{
- if ( mStatus == STATUS_PLAYING || mStatus == STATUS_PAUSED )
+ if ( mStatus == STATUS_PLAYING || mStatus == STATUS_PAUSED || mStatus == STATUS_DONE )
{
if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK )
{
@@ -547,12 +547,12 @@ private:
// see if title arrived and if so, update member variable with contents
checkTitle();
-
- // special code for looping - need to rewind at the end of the movie
- if ( mIsLooping )
+
+ // QT call to see if we are at the end - can't do with controller
+ if ( IsMovieDone( mMovieHandle ) )
{
- // QT call to see if we are at the end - can't do with controller
- if ( IsMovieDone( mMovieHandle ) )
+ // special code for looping - need to rewind at the end of the movie
+ if ( mIsLooping )
{
// go back to start
rewind();
@@ -565,8 +565,16 @@ private:
// set the volume
MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume );
};
- };
- };
+ }
+ else
+ {
+ if(mStatus == STATUS_PLAYING)
+ {
+ setStatus(STATUS_DONE);
+ }
+ }
+ }
+
};
int getDataWidth() const
diff --git a/indra/media_plugins/webkit/media_plugin_webkit.cpp b/indra/media_plugins/webkit/media_plugin_webkit.cpp
index e42f9739f4..3ce8ff3deb 100644
--- a/indra/media_plugins/webkit/media_plugin_webkit.cpp
+++ b/indra/media_plugins/webkit/media_plugin_webkit.cpp
@@ -83,6 +83,7 @@ private:
bool mCanPaste;
int mLastMouseX;
int mLastMouseY;
+ bool mFirstFocus;
////////////////////////////////////////////////////////////////////////////////
//
@@ -206,14 +207,13 @@ private:
// don't flip bitmap
LLQtWebKit::getInstance()->flipWindow( mBrowserWindowId, true );
- // Set the background color to black
- LLQtWebKit::getInstance()->
// set background color to be black - mostly for initial login page
LLQtWebKit::getInstance()->setBackgroundColor( mBrowserWindowId, 0x00, 0x00, 0x00 );
- // go to the "home page"
// Don't do this here -- it causes the dreaded "white flash" when loading a browser instance.
-// LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, "about:blank" );
+ // FIXME: Re-added this because navigating to a "page" initializes things correctly - especially
+ // for the HTTP AUTH dialog issues (DEV-41731). Will fix at a later date.
+ LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, "about:blank" );
// set flag so we don't do this again
mBrowserInitialized = true;
@@ -495,6 +495,7 @@ MediaPluginWebKit::MediaPluginWebKit(LLPluginInstance::sendMessageFunction host_
mCanPaste = false;
mLastMouseX = 0;
mLastMouseY = 0;
+ mFirstFocus = true;
}
MediaPluginWebKit::~MediaPluginWebKit()
@@ -769,6 +770,15 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
{
bool val = message_in.getValueBoolean("focused");
LLQtWebKit::getInstance()->focusBrowser( mBrowserWindowId, val );
+
+ if(mFirstFocus && val)
+ {
+ // On the first focus, post a tab key event. This fixes a problem with initial focus.
+ std::string empty;
+ keyEvent(LLQtWebKit::KE_KEY_DOWN, KEY_TAB, decodeModifiers(empty));
+ keyEvent(LLQtWebKit::KE_KEY_UP, KEY_TAB, decodeModifiers(empty));
+ mFirstFocus = false;
+ }
}
else if(message_name == "clear_cache")
{
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index dd3937a6ef..a7681e4a1d 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -63,13 +63,13 @@ include_directories(
)
set(viewer_SOURCE_FILES
- llaccordionctrltab.cpp
llaccordionctrl.cpp
+ llaccordionctrltab.cpp
llagent.cpp
- llagentlistener.cpp
llagentaccess.cpp
llagentdata.cpp
llagentlanguage.cpp
+ llagentlistener.cpp
llagentpicksinfo.cpp
llagentpilot.cpp
llagentui.cpp
@@ -78,8 +78,8 @@ set(viewer_SOURCE_FILES
llappearancemgr.cpp
llappviewer.cpp
llappviewerlistener.cpp
- llassetuploadresponders.cpp
llassetuploadqueue.cpp
+ llassetuploadresponders.cpp
llaudiosourcevo.cpp
llavataractions.cpp
llavatariconctrl.cpp
@@ -95,8 +95,8 @@ set(viewer_SOURCE_FILES
llcaphttpsender.cpp
llchannelmanager.cpp
llchatbar.cpp
- llchatitemscontainerctrl.cpp
llchathistory.cpp
+ llchatitemscontainerctrl.cpp
llchatmsgbox.cpp
llchiclet.cpp
llclassifiedinfo.cpp
@@ -116,10 +116,10 @@ set(viewer_SOURCE_FILES
lldirpicker.cpp
lldndbutton.cpp
lldrawable.cpp
+ lldrawpool.cpp
lldrawpoolalpha.cpp
lldrawpoolavatar.cpp
lldrawpoolbump.cpp
- lldrawpool.cpp
lldrawpoolground.cpp
lldrawpoolsimple.cpp
lldrawpoolsky.cpp
@@ -151,8 +151,8 @@ set(viewer_SOURCE_FILES
llfloaterbuildoptions.cpp
llfloaterbulkpermission.cpp
llfloaterbump.cpp
- llfloaterbuycontents.cpp
llfloaterbuy.cpp
+ llfloaterbuycontents.cpp
llfloaterbuycurrency.cpp
llfloaterbuyland.cpp
llfloatercall.cpp
@@ -163,8 +163,8 @@ set(viewer_SOURCE_FILES
llfloatercustomize.cpp
llfloaterdaycycle.cpp
llfloaterenvsettings.cpp
- llfloaterfriends.cpp
llfloaterfonttest.cpp
+ llfloaterfriends.cpp
llfloatergesture.cpp
llfloatergodtools.cpp
llfloatergroupinvite.cpp
@@ -172,8 +172,6 @@ set(viewer_SOURCE_FILES
llfloaterhandler.cpp
llfloaterhardwaresettings.cpp
llfloaterhelpbrowser.cpp
- llfloatermediabrowser.cpp
- llfloatermediasettings.cpp
llfloaterhud.cpp
llfloaterimagepreview.cpp
llfloaterinspect.cpp
@@ -183,6 +181,8 @@ set(viewer_SOURCE_FILES
llfloaterland.cpp
llfloaterlandholdings.cpp
llfloatermap.cpp
+ llfloatermediabrowser.cpp
+ llfloatermediasettings.cpp
llfloatermemleak.cpp
llfloaternamedesc.cpp
llfloaternotificationsconsole.cpp
@@ -227,8 +227,8 @@ set(viewer_SOURCE_FILES
llgroupmgr.cpp
llgroupnotify.cpp
llhomelocationresponder.cpp
- llhudeffectbeam.cpp
llhudeffect.cpp
+ llhudeffectbeam.cpp
llhudeffectlookat.cpp
llhudeffectpointat.cpp
llhudeffecttrail.cpp
@@ -238,11 +238,11 @@ set(viewer_SOURCE_FILES
llhudrender.cpp
llhudtext.cpp
llhudview.cpp
+ llimcontrolpanel.cpp
llimfloater.cpp
llimhandler.cpp
llimpanel.cpp
llimview.cpp
- llimcontrolpanel.cpp
llinspect.cpp
llinspectavatar.cpp
llinspectgroup.cpp
@@ -260,7 +260,6 @@ set(viewer_SOURCE_FILES
lllocaltextureobject.cpp
lllocationhistory.cpp
lllocationinputctrl.cpp
- llurllineeditorctrl.cpp
lllogchat.cpp
llloginhandler.cpp
lllogininstance.cpp
@@ -312,8 +311,8 @@ set(viewer_SOURCE_FILES
llpanelgrouplandmoney.cpp
llpanelgroupnotices.cpp
llpanelgrouproles.cpp
- llpanelinventory.cpp
llpanelimcontrolpanel.cpp
+ llpanelinventory.cpp
llpanelland.cpp
llpanellandaudio.cpp
llpanellandmarks.cpp
@@ -322,11 +321,10 @@ set(viewer_SOURCE_FILES
llpanellookinfo.cpp
llpanellooks.cpp
llpanelmedia.cpp
- llpanelmediahud.cpp
- llpanelmeprofile.cpp
llpanelmediasettingsgeneral.cpp
- llpanelmediasettingssecurity.cpp
llpanelmediasettingspermissions.cpp
+ llpanelmediasettingssecurity.cpp
+ llpanelmeprofile.cpp
llpanelobject.cpp
llpanelpeople.cpp
llpanelpeoplemenus.cpp
@@ -335,11 +333,12 @@ set(viewer_SOURCE_FILES
llpanelpicks.cpp
llpanelplace.cpp
llpanelplaceinfo.cpp
- llpanelshower.cpp
llpanelplaces.cpp
llpanelplacestab.cpp
+ llpanelprimmediacontrols.cpp
llpanelprofile.cpp
llpanelprofileview.cpp
+ llpanelshower.cpp
llpanelteleporthistory.cpp
llpanelvolume.cpp
llparcelselection.cpp
@@ -348,8 +347,8 @@ set(viewer_SOURCE_FILES
llplacesinventorybridge.cpp
llpolymesh.cpp
llpolymorph.cpp
- llpreviewanim.cpp
llpreview.cpp
+ llpreviewanim.cpp
llpreviewgesture.cpp
llpreviewnotecard.cpp
llpreviewscript.cpp
@@ -371,6 +370,7 @@ set(viewer_SOURCE_FILES
llsky.cpp
llslurl.cpp
llspatialpartition.cpp
+ llspeakers.cpp
llsplitbutton.cpp
llsprite.cpp
llstartup.cpp
@@ -397,10 +397,10 @@ set(viewer_SOURCE_FILES
lltoastimpanel.cpp
lltoastnotifypanel.cpp
lltoastpanel.cpp
+ lltool.cpp
lltoolbar.cpp
lltoolbrush.cpp
lltoolcomp.cpp
- lltool.cpp
lltooldraganddrop.cpp
lltoolface.cpp
lltoolfocus.cpp
@@ -424,6 +424,7 @@ set(viewer_SOURCE_FILES
llurl.cpp
llurldispatcher.cpp
llurlhistory.cpp
+ llurllineeditorctrl.cpp
llurlsimstring.cpp
llurlwhitelist.cpp
llvectorperfoptions.cpp
@@ -440,18 +441,18 @@ set(viewer_SOURCE_FILES
llviewerhelp.cpp
llviewerhelputil.cpp
llviewerinventory.cpp
- llviewerjointattachment.cpp
llviewerjoint.cpp
+ llviewerjointattachment.cpp
llviewerjointmesh.cpp
- llviewerjointmesh_sse2.cpp
llviewerjointmesh_sse.cpp
+ llviewerjointmesh_sse2.cpp
llviewerjointmesh_vec.cpp
llviewerjoystick.cpp
llviewerkeyboard.cpp
llviewerlayer.cpp
llviewermedia.cpp
- llviewermediafocus.cpp
llviewermedia_streamingaudio.cpp
+ llviewermediafocus.cpp
llviewermenu.cpp
llviewermenufile.cpp
llviewermessage.cpp
@@ -484,10 +485,11 @@ set(viewer_SOURCE_FILES
llvoclouds.cpp
llvograss.cpp
llvoground.cpp
+ llvoicechannel.cpp
llvoiceclient.cpp
+ llvoicecontrolpanel.cpp
llvoiceremotectrl.cpp
llvoicevisualizer.cpp
- llvoicecontrolpanel.cpp
llvoinventorylistener.cpp
llvopartgroup.cpp
llvosky.cpp
@@ -538,25 +540,25 @@ endif (LINUX)
set(viewer_HEADER_FILES
CMakeLists.txt
ViewerInstall.cmake
- llaccordionctrltab.h
llaccordionctrl.h
+ llaccordionctrltab.h
llagent.h
- llagentlistener.h
llagentaccess.h
llagentdata.h
llagentlanguage.h
+ llagentlistener.h
llagentpicksinfo.h
llagentpilot.h
llagentui.h
llagentwearables.h
llanimstatelabels.h
llappearance.h
+ llappearancemgr.h
llappviewer.h
llappviewerlistener.h
- llassetuploadresponders.h
llassetuploadqueue.h
+ llassetuploadresponders.h
llaudiosourcevo.h
- llappearancemgr.h
llavataractions.h
llavatariconctrl.h
llavatarlist.h
@@ -572,8 +574,8 @@ set(viewer_HEADER_FILES
llcaphttpsender.h
llchannelmanager.h
llchatbar.h
- llchatitemscontainerctrl.h
llchathistory.h
+ llchatitemscontainerctrl.h
llchatmsgbox.h
llchiclet.h
llclassifiedinfo.h
@@ -650,8 +652,6 @@ set(viewer_HEADER_FILES
llfloaterhandler.h
llfloaterhardwaresettings.h
llfloaterhelpbrowser.h
- llfloatermediabrowser.h
- llfloatermediasettings.h
llfloaterhud.h
llfloaterimagepreview.h
llfloaterinspect.h
@@ -661,16 +661,18 @@ set(viewer_HEADER_FILES
llfloaterland.h
llfloaterlandholdings.h
llfloatermap.h
+ llfloatermediabrowser.h
+ llfloatermediasettings.h
llfloatermemleak.h
llfloaternamedesc.h
llfloaternotificationsconsole.h
llfloateropenobject.h
llfloaterparcel.h
llfloaterpay.h
+ llfloaterperms.h
llfloaterpostcard.h
llfloaterpostprocess.h
llfloaterpreference.h
- llfloaterperms.h
llfloaterproperties.h
llfloaterregioninfo.h
llfloaterreporter.h
@@ -716,12 +718,12 @@ set(viewer_HEADER_FILES
llhudrender.h
llhudtext.h
llhudview.h
+ llimcontrolpanel.h
llimfloater.h
llimpanel.h
llimview.h
- llimcontrolpanel.h
- llinspectavatar.h
llinspect.h
+ llinspectavatar.h
llinspectgroup.h
llinspectobject.h
llinventorybridge.h
@@ -738,7 +740,6 @@ set(viewer_HEADER_FILES
lllocaltextureobject.h
lllocationhistory.h
lllocationinputctrl.h
- llurllineeditorctrl.h
lllogchat.h
llloginhandler.h
lllogininstance.h
@@ -747,6 +748,7 @@ set(viewer_HEADER_FILES
llmanipscale.h
llmaniptranslate.h
llmapresponders.h
+ llmediactrl.h
llmediadataclient.h
llmediaremotectrl.h
llmemoryview.h
@@ -786,8 +788,8 @@ set(viewer_HEADER_FILES
llpanelgrouplandmoney.h
llpanelgroupnotices.h
llpanelgrouproles.h
- llpanelinventory.h
llpanelimcontrolpanel.h
+ llpanelinventory.h
llpanelland.h
llpanellandaudio.h
llpanellandmarks.h
@@ -796,11 +798,10 @@ set(viewer_HEADER_FILES
llpanellookinfo.h
llpanellooks.h
llpanelmedia.h
- llpanelmediahud.h
- llpanelmeprofile.h
llpanelmediasettingsgeneral.h
- llpanelmediasettingssecurity.h
llpanelmediasettingspermissions.h
+ llpanelmediasettingssecurity.h
+ llpanelmeprofile.h
llpanelobject.h
llpanelpeople.h
llpanelpeoplemenus.h
@@ -809,11 +810,12 @@ set(viewer_HEADER_FILES
llpanelpicks.h
llpanelplace.h
llpanelplaceinfo.h
- llpanelshower.h
llpanelplaces.h
llpanelplacestab.h
+ llpanelprimmediacontrols.h
llpanelprofile.h
llpanelprofileview.h
+ llpanelshower.h
llpanelteleporthistory.h
llpanelvolume.h
llparcelselection.h
@@ -836,9 +838,9 @@ set(viewer_HEADER_FILES
llremoteparcelrequest.h
llresourcedata.h
llrootview.h
+ llsavedsettingsglue.h
llscreenchannel.h
llscrollingpanelparam.h
- llsavedsettingsglue.h
llsearchcombobox.h
llsearchhistory.h
llselectmgr.h
@@ -847,6 +849,7 @@ set(viewer_HEADER_FILES
llsky.h
llslurl.h
llspatialpartition.h
+ llspeakers.h
llsplitbutton.h
llsprite.h
llstartup.h
@@ -902,6 +905,7 @@ set(viewer_HEADER_FILES
llurl.h
llurldispatcher.h
llurlhistory.h
+ llurllineeditorctrl.h
llurlsimstring.h
llurlwhitelist.h
llvectorperfoptions.h
@@ -925,8 +929,8 @@ set(viewer_HEADER_FILES
llviewerkeyboard.h
llviewerlayer.h
llviewermedia.h
- llviewermediaobserver.h
llviewermediafocus.h
+ llviewermediaobserver.h
llviewermenu.h
llviewermenufile.h
llviewermessage.h
@@ -960,10 +964,11 @@ set(viewer_HEADER_FILES
llvoclouds.h
llvograss.h
llvoground.h
+ llvoicechannel.h
llvoiceclient.h
+ llvoicecontrolpanel.h
llvoiceremotectrl.h
llvoicevisualizer.h
- llvoicecontrolpanel.h
llvoinventorylistener.h
llvopartgroup.h
llvosky.h
@@ -981,7 +986,6 @@ set(viewer_HEADER_FILES
llwearabledictionary.h
llwearablelist.h
llweb.h
- llmediactrl.h
llwind.h
llwindebug.h
llwlanimator.h
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 5e6678131d..f9d4a06de8 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -7742,6 +7742,39 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>FriendsListShowIcons</key>
+ <map>
+ <key>Comment</key>
+ <string>Show/hide online and all friends icons in the friend list</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>NearbyListShowIcons</key>
+ <map>
+ <key>Comment</key>
+ <string>Show/hide people icons in nearby list</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>RecentListShowIcons</key>
+ <map>
+ <key>Comment</key>
+ <string>Show/hide people icons in recent list</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>FriendsSortOrder</key>
<map>
<key>Comment</key>
@@ -10449,6 +10482,17 @@
<key>Value</key>
<real>90.0</real>
</map>
+ <key>YouAreHereDistance</key>
+ <map>
+ <key>Comment</key>
+ <string>Radius of distance for banner that indicates if the resident is "on" the Place.(meters from avatar to requested place)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>10.0</real>
+ </map>
<key>YieldTime</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml
index f3bfa37cea..c43ba27984 100644
--- a/indra/newview/character/avatar_lad.xml
+++ b/indra/newview/character/avatar_lad.xml
@@ -5589,6 +5589,13 @@
</layer>
<layer
+ name="hair texture alpha layer"
+ visibility_mask="TRUE">
+ <texture
+ local_texture="hair_grain" />
+ </layer>
+
+ <layer
name="hair alpha"
visibility_mask="TRUE">
<texture
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index f62606cc50..75a72e5b17 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -42,7 +42,7 @@
#include "lldrawable.h"
#include "llfirstuse.h"
#include "llfloaterreg.h"
-#include "llfloateractivespeakers.h"
+#include "llspeakers.h"
#include "llfloatercamera.h"
#include "llfloatercustomize.h"
@@ -5391,12 +5391,6 @@ void update_group_floaters(const LLUUID& group_id)
//*TODO Implement group update for Profile View
// still actual as of July 31, 2009 (DZ)
- if (gIMMgr)
- {
- // update the talk view
- gIMMgr->refresh();
- }
-
gAgent.fireEvent(new LLOldEvents::LLEvent(&gAgent, "new group"), "");
}
diff --git a/indra/newview/llagentui.cpp b/indra/newview/llagentui.cpp
index 1a69f1d975..09f7c49f23 100644
--- a/indra/newview/llagentui.cpp
+++ b/indra/newview/llagentui.cpp
@@ -89,6 +89,11 @@ std::string LLAgentUI::buildSLURL(const bool escaped /*= true*/)
return slurl;
}
+//static
+BOOL LLAgentUI::checkAgentDistance(const LLVector3& pole, F32 radius)
+{
+ return (gAgent.getPositionAgent() - pole).length() < radius;
+}
BOOL LLAgentUI::buildLocationString(std::string& str, ELocationFormat fmt,const LLVector3& agent_pos_region)
{
LLViewerRegion* region = gAgent.getRegion();
diff --git a/indra/newview/llagentui.h b/indra/newview/llagentui.h
index 47ecb04547..c7aafb71e7 100644
--- a/indra/newview/llagentui.h
+++ b/indra/newview/llagentui.h
@@ -52,6 +52,11 @@ public:
static BOOL buildLocationString(std::string& str, ELocationFormat fmt = LOCATION_FORMAT_LANDMARK);
//build location string using a region position of the avatar.
static BOOL buildLocationString(std::string& str, ELocationFormat fmt,const LLVector3& agent_pos_region);
+ /**
+ * @brief Check whether the agent is in neighborhood of the pole Within same region
+ * @return true if the agent is in neighborhood.
+ */
+ static BOOL checkAgentDistance(const LLVector3& local_pole, F32 radius);
};
#endif //LLAGENTUI_H
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index b9a0b4293d..89a7d8b91f 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -1985,6 +1985,17 @@ bool LLAgentWearables::canWearableBeRemoved(const LLWearable* wearable) const
return !(((type == WT_SHAPE) || (type == WT_SKIN) || (type == WT_HAIR) || (type == WT_EYES))
&& (getWearableCount(type) <= 1) );
}
+void LLAgentWearables::animateAllWearableParams(F32 delta, BOOL set_by_user)
+{
+ for( S32 type = 0; type < WT_COUNT; ++type )
+ {
+ for (S32 count = 0; count < (U32)getWearableCount((EWearableType)type); ++count)
+ {
+ LLWearable *wearable = getWearable((EWearableType)type,count);
+ wearable->animateParams(delta, set_by_user);
+ }
+ }
+}
void LLAgentWearables::updateServer()
{
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index 667cb94552..97de785c87 100644
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -79,6 +79,8 @@ public:
// Note: False for shape, skin, eyes, and hair, unless you have MORE than 1.
bool canWearableBeRemoved(const LLWearable* wearable) const;
+
+ void animateAllWearableParams(F32 delta, BOOL set_by_user);
//--------------------------------------------------------------------
// Accessors
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 4610437f08..06c9171d67 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -49,7 +49,6 @@
#include "llviewerstats.h"
#include "llmd5.h"
#include "llpumpio.h"
-#include "llimpanel.h"
#include "llmimetypes.h"
#include "llslurl.h"
#include "llstartup.h"
@@ -76,6 +75,7 @@
#include "llteleporthistory.h"
#include "lllocationhistory.h"
#include "llfasttimerview.h"
+#include "llvoicechannel.h"
#include "llweb.h"
#include "llsecondlifeurls.h"
@@ -1349,6 +1349,8 @@ bool LLAppViewer::cleanup()
if( gViewerWindow)
gViewerWindow->shutdownViews();
+ // Cleanup Inventory after the UI since it will delete any remaining observers
+ // (Deleted observers should have already removed themselves)
gInventory.cleanupInventory();
// Clean up selection managers after UI is destroyed, as UI may be observing them.
diff --git a/indra/newview/llavatariconctrl.h b/indra/newview/llavatariconctrl.h
index 426fcec514..65b5c86ed5 100644
--- a/indra/newview/llavatariconctrl.h
+++ b/indra/newview/llavatariconctrl.h
@@ -103,6 +103,8 @@ public:
const std::string& getFirstName() const { return mFirstName; }
const std::string& getLastName() const { return mLastName; }
+ void setDrawTooltip(bool value) { mDrawTooltip = value;}
+
protected:
LLUUID mAvatarId;
std::string mFirstName;
diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp
index 3a07c6e5ef..65a2b8b5e6 100644
--- a/indra/newview/llavatarlist.cpp
+++ b/indra/newview/llavatarlist.cpp
@@ -37,14 +37,34 @@
// newview
#include "llcallingcard.h" // for LLAvatarTracker
#include "llcachename.h"
+#include "llrecentpeople.h"
#include "llvoiceclient.h"
+#include "llviewercontrol.h" // for gSavedSettings
static LLDefaultChildRegistry::Register<LLAvatarList> r("avatar_list");
+// Last interaction time update period.
+static const F32 LIT_UPDATE_PERIOD = 5;
+
// Maximum number of avatars that can be added to a list in one pass.
// Used to limit time spent for avatar list update per frame.
static const unsigned ADD_LIMIT = 50;
+void LLAvatarList::toggleIcons()
+{
+ // Save the new value for new items to use.
+ mShowIcons = !mShowIcons;
+ gSavedSettings.setBOOL(mIconParamName, mShowIcons);
+
+ // Show/hide icons for all existing items.
+ std::vector<LLPanel*> items;
+ getItems(items);
+ for( std::vector<LLPanel*>::const_iterator it = items.begin(); it != items.end(); it++)
+ {
+ static_cast<LLAvatarListItem*>(*it)->setAvatarIconVisible(mShowIcons);
+ }
+}
+
static bool findInsensitive(std::string haystack, const std::string& needle_upper)
{
LLStringUtil::toUpper(haystack);
@@ -58,28 +78,58 @@ static const LLFlatListView::ItemReverseComparator REVERSE_NAME_COMPARATOR(NAME_
LLAvatarList::Params::Params()
: ignore_online_status("ignore_online_status", false)
+, show_last_interaction_time("show_last_interaction_time", false)
{
}
LLAvatarList::LLAvatarList(const Params& p)
: LLFlatListView(p)
, mIgnoreOnlineStatus(p.ignore_online_status)
+, mShowLastInteractionTime(p.show_last_interaction_time)
, mContextMenu(NULL)
, mDirty(true) // to force initial update
+, mLITUpdateTimer(NULL)
{
setCommitOnSelectionChange(true);
// Set default sort order.
setComparator(&NAME_COMPARATOR);
+
+ if (mShowLastInteractionTime)
+ {
+ mLITUpdateTimer = new LLTimer();
+ mLITUpdateTimer->setTimerExpirySec(0); // zero to force initial update
+ mLITUpdateTimer->start();
+ }
+}
+
+LLAvatarList::~LLAvatarList()
+{
+ delete mLITUpdateTimer;
+}
+
+void LLAvatarList::setShowIcons(std::string param_name)
+{
+ mIconParamName= param_name;
+ mShowIcons = gSavedSettings.getBOOL(mIconParamName);
}
// virtual
void LLAvatarList::draw()
{
+ // *NOTE dzaporozhan
+ // Call refresh() after draw() to avoid flickering of avatar list items.
+
+ LLFlatListView::draw();
+
if (mDirty)
refresh();
- LLFlatListView::draw();
+ if (mShowLastInteractionTime && mLITUpdateTimer->hasExpired())
+ {
+ updateLastInteractionTimes();
+ mLITUpdateTimer->setTimerExpirySec(LIT_UPDATE_PERIOD); // restart the timer
+ }
}
void LLAvatarList::setNameFilter(const std::string& filter)
@@ -193,15 +243,16 @@ void LLAvatarList::refresh()
void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is_online, EAddPosition pos)
{
LLAvatarListItem* item = new LLAvatarListItem();
- item->showStatus(false);
item->showInfoBtn(true);
item->showSpeakingIndicator(true);
item->setName(name);
item->setAvatarId(id, mIgnoreOnlineStatus);
item->setOnline(mIgnoreOnlineStatus ? true : is_online);
+ item->showLastInteractionTime(mShowLastInteractionTime);
item->setContextMenu(mContextMenu);
item->childSetVisible("info_btn", false);
+ item->setAvatarIconVisible(mShowIcons);
addItem(item, id, pos);
}
@@ -253,6 +304,54 @@ void LLAvatarList::computeDifference(
vadded.erase(it, vadded.end());
}
+static std::string format_secs(S32 secs)
+{
+ // *TODO: reinventing the wheel?
+ // *TODO: i18n
+ static const int LL_AL_MIN = 60;
+ static const int LL_AL_HOUR = LL_AL_MIN * 60;
+ static const int LL_AL_DAY = LL_AL_HOUR * 24;
+ static const int LL_AL_WEEK = LL_AL_DAY * 7;
+ static const int LL_AL_MONTH = LL_AL_DAY * 31;
+ static const int LL_AL_YEAR = LL_AL_DAY * 365;
+
+ std::string s;
+
+ if (secs >= LL_AL_YEAR)
+ s = llformat("%dy", secs / LL_AL_YEAR);
+ else if (secs >= LL_AL_MONTH)
+ s = llformat("%dmon", secs / LL_AL_MONTH);
+ else if (secs >= LL_AL_WEEK)
+ s = llformat("%dw", secs / LL_AL_WEEK);
+ else if (secs >= LL_AL_DAY)
+ s = llformat("%dd", secs / LL_AL_DAY);
+ else if (secs >= LL_AL_HOUR)
+ s = llformat("%dh", secs / LL_AL_HOUR);
+ else if (secs >= LL_AL_MIN)
+ s = llformat("%dm", secs / LL_AL_MIN);
+ else
+ s = llformat("%ds", secs);
+
+ return s;
+}
+
+// Refresh shown time of our last interaction with all listed avatars.
+void LLAvatarList::updateLastInteractionTimes()
+{
+ S32 now = (S32) LLDate::now().secondsSinceEpoch();
+ std::vector<LLPanel*> items;
+ getItems(items);
+
+ for( std::vector<LLPanel*>::const_iterator it = items.begin(); it != items.end(); it++)
+ {
+ // *TODO: error handling
+ LLAvatarListItem* item = static_cast<LLAvatarListItem*>(*it);
+ S32 secs_since = now - (S32) LLRecentPeople::instance().getDate(item->getAvatarId()).secondsSinceEpoch();
+ if (secs_since >= 0)
+ item->setLastInteractionTime(format_secs(secs_since));
+ }
+}
+
bool LLAvatarItemComparator::compare(const LLPanel* item1, const LLPanel* item2) const
{
const LLAvatarListItem* avatar_item1 = dynamic_cast<const LLAvatarListItem*>(item1);
diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h
index a83a72b26c..8f2f0249a6 100644
--- a/indra/newview/llavatarlist.h
+++ b/indra/newview/llavatarlist.h
@@ -37,6 +37,8 @@
#include "llavatarlistitem.h"
+class LLTimer;
+
/**
* Generic list of avatars.
*
@@ -56,11 +58,12 @@ public:
struct Params : public LLInitParam::Block<Params, LLFlatListView::Params>
{
Optional<bool> ignore_online_status; // show all items as online
+ Optional<bool> show_last_interaction_time; // show most recent interaction time. *HACK: move this to a derived class
Params();
};
LLAvatarList(const Params&);
- virtual ~LLAvatarList() {}
+ virtual ~LLAvatarList();
virtual void draw(); // from LLView
@@ -70,7 +73,11 @@ public:
void setContextMenu(LLAvatarListItem::ContextMenu* menu) { mContextMenu = menu; }
+ void toggleIcons();
void sortByName();
+ void setShowIcons(std::string param_name);
+ bool getIconsVisible() const { return mShowIcons; }
+ const std::string getIconParamName() const{return mIconParamName;}
virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
protected:
@@ -81,12 +88,17 @@ protected:
const std::vector<LLUUID>& vnew,
std::vector<LLUUID>& vadded,
std::vector<LLUUID>& vremoved);
+ void updateLastInteractionTimes();
private:
bool mIgnoreOnlineStatus;
+ bool mShowLastInteractionTime;
bool mDirty;
+ bool mShowIcons;
+ LLTimer* mLITUpdateTimer; // last interaction time update timer
+ std::string mIconParamName;
std::string mNameFilter;
uuid_vector_t mIDs;
diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp
index ebc79aae48..8464430501 100644
--- a/indra/newview/llavatarlistitem.cpp
+++ b/indra/newview/llavatarlistitem.cpp
@@ -42,12 +42,13 @@
#include "llavatariconctrl.h"
#include "llbutton.h"
+S32 LLAvatarListItem::sIconWidth = 0;
LLAvatarListItem::LLAvatarListItem()
: LLPanel(),
mAvatarIcon(NULL),
mAvatarName(NULL),
- mStatus(NULL),
+ mLastInteractionTime(NULL),
mSpeakingIndicator(NULL),
mInfoBtn(NULL),
mProfileBtn(NULL),
@@ -55,6 +56,12 @@ LLAvatarListItem::LLAvatarListItem()
mOnlineStatus(E_UNKNOWN)
{
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_avatar_list_item.xml");
+ // Remember avatar icon width including its padding from the name text box,
+ // so that we can hide and show the icon again later.
+ if (!sIconWidth)
+ {
+ sIconWidth = mAvatarName->getRect().mLeft - mAvatarIcon->getRect().mLeft;
+ }
}
LLAvatarListItem::~LLAvatarListItem()
@@ -67,8 +74,8 @@ BOOL LLAvatarListItem::postBuild()
{
mAvatarIcon = getChild<LLAvatarIconCtrl>("avatar_icon");
mAvatarName = getChild<LLTextBox>("avatar_name");
- mStatus = getChild<LLTextBox>("avatar_status");
-
+ mLastInteractionTime = getChild<LLTextBox>("last_interaction");
+
mSpeakingIndicator = getChild<LLOutputMonitorCtrl>("speaking_indicator");
mInfoBtn = getChild<LLButton>("info_btn");
mProfileBtn = getChild<LLButton>("profile_btn");
@@ -90,12 +97,6 @@ BOOL LLAvatarListItem::postBuild()
rect.setLeftTopAndSize(mName->getRect().mLeft, mName->getRect().mTop, mName->getRect().getWidth() + 30, mName->getRect().getHeight());
mName->setRect(rect);
- if(mStatus)
- {
- rect.setLeftTopAndSize(mStatus->getRect().mLeft + 30, mStatus->getRect().mTop, mStatus->getRect().getWidth(), mStatus->getRect().getHeight());
- mStatus->setRect(rect);
- }
-
if(mLocator)
{
rect.setLeftTopAndSize(mLocator->getRect().mLeft + 30, mLocator->getRect().mTop, mLocator->getRect().getWidth(), mLocator->getRect().getHeight());
@@ -130,11 +131,6 @@ void LLAvatarListItem::onMouseLeave(S32 x, S32 y, MASK mask)
LLPanel::onMouseLeave(x, y, mask);
}
-void LLAvatarListItem::setStatus(const std::string& status)
-{
- mStatus->setValue(status);
-}
-
// virtual, called by LLAvatarTracker
void LLAvatarListItem::changed(U32 mask)
{
@@ -188,6 +184,39 @@ void LLAvatarListItem::setAvatarId(const LLUUID& id, bool ignore_status_changes)
gCacheName->get(id, FALSE, boost::bind(&LLAvatarListItem::onNameCache, this, _2, _3));
}
+void LLAvatarListItem::showLastInteractionTime(bool show)
+{
+ if (show)
+ return;
+
+ LLRect name_rect = mAvatarName->getRect();
+ LLRect time_rect = mLastInteractionTime->getRect();
+
+ mLastInteractionTime->setVisible(false);
+ name_rect.mRight += (time_rect.mRight - name_rect.mRight);
+ mAvatarName->setRect(name_rect);
+}
+
+void LLAvatarListItem::setLastInteractionTime(const std::string& val)
+{
+ mLastInteractionTime->setValue(val);
+}
+
+void LLAvatarListItem::setAvatarIconVisible(bool visible)
+{
+ // Already done? Then do nothing.
+ if (mAvatarIcon->getVisible() == (BOOL)visible)
+ return;
+
+ // Show/hide avatar icon.
+ mAvatarIcon->setVisible(visible);
+
+ // Move the avatar name horizontally by icon size + its distance from the avatar name.
+ LLRect name_rect = mAvatarName->getRect();
+ name_rect.mLeft += visible ? sIconWidth : -sIconWidth;
+ mAvatarName->setRect(name_rect);
+}
+
void LLAvatarListItem::onInfoBtnClick()
{
LLFloaterReg::showInstance("inspect_avatar", LLSD().insert("avatar_id", mAvatarId));
@@ -218,21 +247,6 @@ void LLAvatarListItem::onProfileBtnClick()
LLAvatarActions::showProfile(mAvatarId);
}
-void LLAvatarListItem::showStatus(bool show_status)
-{
- // *HACK: dirty hack until we can determine correct avatar status (EXT-1076).
-
- if (show_status)
- return;
-
- LLRect name_rect = mAvatarName->getRect();
- LLRect status_rect = mStatus->getRect();
-
- mStatus->setVisible(show_status);
- name_rect.mRight += (status_rect.mRight - name_rect.mRight);
- mAvatarName->setRect(name_rect);
-}
-
void LLAvatarListItem::setValue( const LLSD& value )
{
if (!value.isMap()) return;;
diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h
index b9cfed4b7b..10c0b17005 100644
--- a/indra/newview/llavatarlistitem.h
+++ b/indra/newview/llavatarlistitem.h
@@ -60,10 +60,11 @@ public:
virtual void setValue(const LLSD& value);
virtual void changed(U32 mask); // from LLFriendObserver
- void setStatus(const std::string& status);
void setOnline(bool online);
void setName(const std::string& name);
void setAvatarId(const LLUUID& id, bool ignore_status_changes = false);
+ void setLastInteractionTime(const std::string& val);
+ void setAvatarIconVisible(bool visible);
const LLUUID& getAvatarId() const;
const std::string getAvatarName() const;
@@ -73,7 +74,7 @@ public:
void showSpeakingIndicator(bool show) { mSpeakingIndicator->setVisible(show); }
void showInfoBtn(bool show_info_btn) {mInfoBtn->setVisible(show_info_btn); }
- void showStatus(bool show_status);
+ void showLastInteractionTime(bool show);
void setContextMenu(ContextMenu* menu) { mContextMenu = menu; }
@@ -87,9 +88,9 @@ private:
void onNameCache(const std::string& first_name, const std::string& last_name);
- LLAvatarIconCtrl*mAvatarIcon;
+ LLAvatarIconCtrl* mAvatarIcon;
LLTextBox* mAvatarName;
- LLTextBox* mStatus;
+ LLTextBox* mLastInteractionTime;
LLOutputMonitorCtrl* mSpeakingIndicator;
LLButton* mInfoBtn;
@@ -98,6 +99,7 @@ private:
LLUUID mAvatarId;
EOnlineStatus mOnlineStatus;
+ static S32 sIconWidth; // icon width + padding
};
#endif //LL_LLAVATARLISTITEM_H
diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp
index 77f941eef0..6427422572 100644
--- a/indra/newview/llchannelmanager.cpp
+++ b/indra/newview/llchannelmanager.cpp
@@ -40,6 +40,8 @@
#include "llbottomtray.h"
#include "llviewerwindow.h"
#include "llrootview.h"
+#include "llsyswellwindow.h"
+#include "llfloaterreg.h"
#include <algorithm>
@@ -128,7 +130,7 @@ void LLChannelManager::onLoginCompleted()
S32 channel_right_bound = gViewerWindow->getWorldViewRect().mRight - gSavedSettings.getS32("NotificationChannelRightMargin");
S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth");
mStartUpChannel->init(channel_right_bound - channel_width, channel_right_bound);
- mStartUpChannel->setShowToasts(true);
+ mStartUpChannel->setMouseDownCallback(boost::bind(&LLSysWellWindow::onStartUpToastClick, LLFloaterReg::getTypedInstance<LLSysWellWindow>("syswell_window"), _2, _3, _4));
mStartUpChannel->setCommitCallback(boost::bind(&LLChannelManager::onStartUpToastClose, this));
mStartUpChannel->createStartUpToast(away_notifications, gSavedSettings.getS32("StartUpToastLifeTime"));
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index 94058365be..e561507e69 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -38,9 +38,251 @@
#include "llscrollcontainer.h"
#include "llavatariconctrl.h"
+#include "llimview.h"
+#include "llcallingcard.h" //for LLAvatarTracker
+#include "llagentdata.h"
+#include "llavataractions.h"
+#include "lltrans.h"
+#include "llfloaterreg.h"
+#include "llmutelist.h"
+
static LLDefaultChildRegistry::Register<LLChatHistory> r("chat_history");
static const std::string MESSAGE_USERNAME_DATE_SEPARATOR(" ----- ");
+std::string formatCurrentTime()
+{
+ time_t utc_time;
+ utc_time = time_corrected();
+ std::string timeStr ="["+ LLTrans::getString("TimeHour")+"]:["
+ +LLTrans::getString("TimeMin")+"] ";
+
+ LLSD substitution;
+
+ substitution["datetime"] = (S32) utc_time;
+ LLStringUtil::format (timeStr, substitution);
+
+ return timeStr;
+}
+
+class LLChatHistoryHeader: public LLPanel
+{
+public:
+ static LLChatHistoryHeader* createInstance(const std::string& file_name)
+ {
+ LLChatHistoryHeader* pInstance = new LLChatHistoryHeader;
+ LLUICtrlFactory::getInstance()->buildPanel(pInstance, file_name);
+ return pInstance;
+ }
+
+ BOOL handleMouseUp(S32 x, S32 y, MASK mask)
+ {
+ return LLPanel::handleMouseUp(x,y,mask);
+ }
+
+ void onObjectIconContextMenuItemClicked(const LLSD& userdata)
+ {
+ std::string level = userdata.asString();
+
+ if (level == "profile")
+ {
+ }
+ else if (level == "block")
+ {
+ LLMuteList::getInstance()->add(LLMute(getAvatarId(), mFrom, LLMute::OBJECT));
+ }
+ }
+
+ void onAvatarIconContextMenuItemClicked(const LLSD& userdata)
+ {
+ std::string level = userdata.asString();
+
+ if (level == "profile")
+ {
+ LLAvatarActions::showProfile(getAvatarId());
+ }
+ else if (level == "im")
+ {
+ LLAvatarActions::startIM(getAvatarId());
+ }
+ else if (level == "add")
+ {
+ std::string name;
+ name.assign(getFirstName());
+ name.append(" ");
+ name.append(getLastName());
+
+ LLAvatarActions::requestFriendshipDialog(getAvatarId(), name);
+ }
+ else if (level == "remove")
+ {
+ LLAvatarActions::removeFriendDialog(getAvatarId());
+ }
+ }
+
+ BOOL postBuild()
+ {
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+
+ registrar.add("AvatarIcon.Action", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemClicked, this, _2));
+ registrar.add("ObjectIcon.Action", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemClicked, this, _2));
+
+ LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_avatar_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ mPopupMenuHandleAvatar = menu->getHandle();
+
+ menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_object_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ mPopupMenuHandleObject = menu->getHandle();
+
+ LLPanel* visible_panel = getChild<LLPanel>("im_header");
+ visible_panel->setMouseDownCallback(boost::bind(&LLChatHistoryHeader::onHeaderPanelClick, this, _2, _3, _4));
+
+ return LLPanel::postBuild();
+ }
+
+ bool pointInChild(const std::string& name,S32 x,S32 y)
+ {
+ LLUICtrl* child = findChild<LLUICtrl>(name);
+ if(!child)
+ return false;
+
+ LLView* parent = child->getParent();
+ if(parent!=this)
+ {
+ x-=parent->getRect().mLeft;
+ y-=parent->getRect().mBottom;
+ }
+
+ S32 local_x = x - child->getRect().mLeft ;
+ S32 local_y = y - child->getRect().mBottom ;
+ return child->pointInView(local_x, local_y);
+ }
+
+ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask)
+ {
+ if(pointInChild("avatar_icon",x,y) || pointInChild("user_name",x,y))
+ {
+ showContextMenu(x,y);
+ return TRUE;
+ }
+
+ return LLPanel::handleRightMouseDown(x,y,mask);
+ }
+
+ void onHeaderPanelClick(S32 x, S32 y, MASK mask)
+ {
+ LLFloaterReg::showInstance("inspect_avatar", LLSD().insert("avatar_id", mAvatarID));
+ }
+
+ const LLUUID& getAvatarId () const { return mAvatarID;}
+ const std::string& getFirstName() const { return mFirstName; }
+ const std::string& getLastName () const { return mLastName; }
+
+ void setup(const LLChat& chat)
+ {
+ mAvatarID = chat.mFromID;
+ mSourceType = chat.mSourceType;
+ gCacheName->get(mAvatarID, FALSE, boost::bind(&LLChatHistoryHeader::nameUpdatedCallback, this, _1, _2, _3, _4));
+ if(chat.mFromID.isNull())
+ {
+ mSourceType = CHAT_SOURCE_SYSTEM;
+ }
+
+
+ LLTextBox* userName = getChild<LLTextBox>("user_name");
+
+ if(!chat.mFromName.empty())
+ {
+ userName->setValue(chat.mFromName);
+ mFrom = chat.mFromName;
+ }
+ else
+ {
+ std::string SL = LLTrans::getString("SECOND_LIFE");
+ userName->setValue(SL);
+ }
+
+ LLTextBox* timeBox = getChild<LLTextBox>("time_box");
+ timeBox->setValue(formatCurrentTime());
+
+ LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>("avatar_icon");
+
+ if(mSourceType != CHAT_SOURCE_AGENT)
+ icon->setDrawTooltip(false);
+
+ if(!chat.mFromID.isNull())
+ {
+ icon->setValue(chat.mFromID);
+ }
+
+ }
+
+ void nameUpdatedCallback(const LLUUID& id,const std::string& first,const std::string& last,BOOL is_group)
+ {
+ if (id != mAvatarID)
+ return;
+ mFirstName = first;
+ mLastName = last;
+ }
+protected:
+ void showContextMenu(S32 x,S32 y)
+ {
+ if(mSourceType == CHAT_SOURCE_SYSTEM)
+ showSystemContextMenu(x,y);
+ if(mSourceType == CHAT_SOURCE_AGENT)
+ showAvatarContextMenu(x,y);
+ if(mSourceType == CHAT_SOURCE_OBJECT)
+ showObjectContextMenu(x,y);
+ }
+
+ void showSystemContextMenu(S32 x,S32 y)
+ {
+ }
+
+ void showObjectContextMenu(S32 x,S32 y)
+ {
+ LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandleObject.get();
+ if(menu)
+ LLMenuGL::showPopup(this, menu, x, y);
+ }
+
+ void showAvatarContextMenu(S32 x,S32 y)
+ {
+ LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandleAvatar.get();
+
+ if(menu)
+ {
+ bool is_friend = LLAvatarTracker::instance().getBuddyInfo(mAvatarID) != NULL;
+
+ menu->setItemEnabled("Add Friend", !is_friend);
+ menu->setItemEnabled("Remove Friend", is_friend);
+
+ if(gAgentID == mAvatarID)
+ {
+ menu->setItemEnabled("Add Friend", false);
+ menu->setItemEnabled("Send IM", false);
+ menu->setItemEnabled("Remove Friend", false);
+ }
+
+ menu->buildDrawLabels();
+ menu->updateParent(LLMenuGL::sMenuContainer);
+ LLMenuGL::showPopup(this, menu, x, y);
+ }
+ }
+
+
+
+protected:
+ LLHandle<LLView> mPopupMenuHandleAvatar;
+ LLHandle<LLView> mPopupMenuHandleObject;
+
+ LLUUID mAvatarID;
+ EChatSourceType mSourceType;
+ std::string mFirstName;
+ std::string mLastName;
+ std::string mFrom;
+
+};
+
+
LLChatHistory::LLChatHistory(const LLChatHistory::Params& p)
: LLTextEditor(p),
mMessageHeaderFilename(p.message_header),
@@ -48,7 +290,7 @@ mMessageSeparatorFilename(p.message_separator),
mLeftTextPad(p.left_text_pad),
mRightTextPad(p.right_text_pad),
mLeftWidgetPad(p.left_widget_pad),
-mRightWidgetPad(p.rigth_widget_pad)
+mRightWidgetPad(p.right_widget_pad)
{
}
@@ -78,50 +320,49 @@ LLView* LLChatHistory::getSeparator()
return separator;
}
-LLView* LLChatHistory::getHeader(const LLUUID& avatar_id, std::string& from, std::string& time)
+LLView* LLChatHistory::getHeader(const LLChat& chat)
{
- LLPanel* header = LLUICtrlFactory::getInstance()->createFromFile<LLPanel>(mMessageHeaderFilename, NULL, LLPanel::child_registry_t::instance());
- LLTextBox* userName = header->getChild<LLTextBox>("user_name");
- userName->setValue(from);
- LLTextBox* timeBox = header->getChild<LLTextBox>("time_box");
- timeBox->setValue(time);
- if(!avatar_id.isNull())
- {
- LLAvatarIconCtrl* icon = header->getChild<LLAvatarIconCtrl>("avatar_icon");
- icon->setValue(avatar_id);
- }
+ LLChatHistoryHeader* header = LLChatHistoryHeader::createInstance(mMessageHeaderFilename);
+ header->setup(chat);
return header;
}
-void LLChatHistory::appendWidgetMessage(const LLUUID& avatar_id, std::string& from, std::string& time, std::string& message, LLStyle::Params& style_params)
+void LLChatHistory::appendWidgetMessage(const LLChat& chat, LLStyle::Params& style_params)
{
LLView* view = NULL;
std::string view_text;
- if (mLastFromName == from)
+ if (mLastFromName == chat.mFromName)
{
view = getSeparator();
view_text = "\n";
}
else
{
- view = getHeader(avatar_id, from, time);
- view_text = from + MESSAGE_USERNAME_DATE_SEPARATOR + time + '\n';
+ view = getHeader(chat);
+ view_text = chat.mFromName + MESSAGE_USERNAME_DATE_SEPARATOR + formatCurrentTime() + '\n';
}
//Prepare the rect for the view
LLRect target_rect = getDocumentView()->getRect();
- target_rect.mLeft += mLeftWidgetPad;
+ // squeeze down the widget by subtracting padding off left and right
+ target_rect.mLeft += mLeftWidgetPad + mHPad;
target_rect.mRight -= mRightWidgetPad;
view->reshape(target_rect.getWidth(), view->getRect().getHeight());
view->setOrigin(target_rect.mLeft, view->getRect().mBottom);
- appendWidget(view, view_text, FALSE, TRUE, mLeftWidgetPad, 0);
+ LLInlineViewSegment::Params p;
+ p.view = view;
+ p.force_newline = true;
+ p.left_pad = mLeftWidgetPad;
+ p.right_pad = mRightWidgetPad;
+
+ appendWidget(p, view_text, false);
//Append the text message
- message += '\n';
+ std::string message = chat.mText + '\n';
appendText(message, FALSE, style_params);
- mLastFromName = from;
+ mLastFromName = chat.mFromName;
blockUndo();
setCursorAndScrollToEnd();
}
diff --git a/indra/newview/llchathistory.h b/indra/newview/llchathistory.h
index d6eccf896a..92dcfdd958 100644
--- a/indra/newview/llchathistory.h
+++ b/indra/newview/llchathistory.h
@@ -34,6 +34,7 @@
#define LLCHATHISTORY_H_
#include "lltexteditor.h"
+#include "llchat.h"
//Chat log widget allowing addition of a message as a widget
class LLChatHistory : public LLTextEditor
@@ -52,7 +53,7 @@ class LLChatHistory : public LLTextEditor
//Widget left padding from the scroll rect
Optional<S32> left_widget_pad;
//Widget right padding from the scroll rect
- Optional<S32> rigth_widget_pad;
+ Optional<S32> right_widget_pad;
Params()
: message_header("message_header"),
@@ -60,7 +61,7 @@ class LLChatHistory : public LLTextEditor
left_text_pad("left_text_pad"),
right_text_pad("right_text_pad"),
left_widget_pad("left_widget_pad"),
- rigth_widget_pad("rigth_widget_pad")
+ right_widget_pad("right_widget_pad")
{
}
@@ -85,7 +86,7 @@ class LLChatHistory : public LLTextEditor
* @param time time of a message.
* @return pointer to LLView header object.
*/
- LLView* getHeader(const LLUUID& avatar_id, std::string& from, std::string& time);
+ LLView* getHeader(const LLChat& chat);
public:
~LLChatHistory();
@@ -94,11 +95,11 @@ class LLChatHistory : public LLTextEditor
* Appends a widget message.
* If last user appended message, concurs with current user,
* separator is added before the message, otherwise header is added.
- * @param from owner of a message.
+ * @param chat - base chat message.
* @param time time of a message.
* @param message message itself.
*/
- void appendWidgetMessage(const LLUUID& avatar_id, std::string& from, std::string& time, std::string& message, LLStyle::Params& style_params);
+ void appendWidgetMessage(const LLChat& chat, LLStyle::Params& style_params);
private:
std::string mLastFromName;
diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp
index 61a60a24be..670f8717a2 100644
--- a/indra/newview/llchiclet.cpp
+++ b/indra/newview/llchiclet.cpp
@@ -37,7 +37,6 @@
#include "llbottomtray.h"
#include "llgroupactions.h"
#include "lliconctrl.h"
-#include "llimpanel.h" // LLFloaterIMPanel
#include "llimfloater.h"
#include "llimview.h"
#include "llfloaterreg.h"
@@ -1398,7 +1397,7 @@ void LLTalkButton::onClick_ShowBtn()
LLAvatarListItem* item = new LLAvatarListItem();
- item->showStatus(true);
+ item->showLastInteractionTime(false);
item->showInfoBtn(true);
item->showSpeakingIndicator(true);
item->reshape(mPrivateCallPanel->getRect().getWidth(), item->getRect().getHeight(), FALSE);
diff --git a/indra/newview/lldriverparam.cpp b/indra/newview/lldriverparam.cpp
index 45f4b4fbd0..527656ab6b 100644
--- a/indra/newview/lldriverparam.cpp
+++ b/indra/newview/lldriverparam.cpp
@@ -224,6 +224,7 @@ void LLDriverParam::setAvatar(LLVOAvatar *avatarp)
}
}
*new_param = *this;
+ new_param->setIsDummy(FALSE);
return new_param;
}
diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
index 3b5b7f570e..a6afbc05be 100644
--- a/indra/newview/llfavoritesbar.cpp
+++ b/indra/newview/llfavoritesbar.cpp
@@ -503,13 +503,15 @@ void LLFavoritesBarCtrl::handleNewFavoriteDragAndDrop(LLInventoryItem *item, con
return;
}
+ LLPointer<LLViewerInventoryItem> viewer_item = new LLViewerInventoryItem(item);
+
if (dest)
{
- insertBeforeItem(mItems, dest->getLandmarkId(), item->getUUID());
+ insertBeforeItem(mItems, dest->getLandmarkId(), viewer_item);
}
else
{
- mItems.push_back(gInventory.getItem(item->getUUID()));
+ mItems.push_back(viewer_item);
}
int sortField = 0;
@@ -534,13 +536,22 @@ void LLFavoritesBarCtrl::handleNewFavoriteDragAndDrop(LLInventoryItem *item, con
}
}
- copy_inventory_item(
- gAgent.getID(),
- item->getPermissions().getOwner(),
- item->getUUID(),
- favorites_id,
- std::string(),
- cb);
+ LLToolDragAndDrop* tool_dad = LLToolDragAndDrop::getInstance();
+ if (tool_dad->getSource() == LLToolDragAndDrop::SOURCE_NOTECARD)
+ {
+ viewer_item->setType(LLAssetType::AT_FAVORITE);
+ copy_inventory_from_notecard(tool_dad->getObjectID(), tool_dad->getSourceID(), viewer_item.get(), gInventoryCallbacks.registerCB(cb));
+ }
+ else
+ {
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ favorites_id,
+ std::string(),
+ cb);
+ }
llinfos << "Copied inventory item #" << item->getUUID() << " to favorites." << llendl;
}
@@ -1263,10 +1274,9 @@ void LLFavoritesBarCtrl::updateItemsOrder(LLInventoryModel::item_array_t& items,
items.insert(findItemByUUID(items, destItem->getUUID()), srcItem);
}
-void LLFavoritesBarCtrl::insertBeforeItem(LLInventoryModel::item_array_t& items, const LLUUID& beforeItemId, const LLUUID& insertedItemId)
+void LLFavoritesBarCtrl::insertBeforeItem(LLInventoryModel::item_array_t& items, const LLUUID& beforeItemId, LLViewerInventoryItem* insertedItem)
{
LLViewerInventoryItem* beforeItem = gInventory.getItem(beforeItemId);
- LLViewerInventoryItem* insertedItem = gInventory.getItem(insertedItemId);
items.insert(findItemByUUID(items, beforeItem->getUUID()), insertedItem);
}
diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h
index ea2a3d08e2..e90d13f9d5 100644
--- a/indra/newview/llfavoritesbar.h
+++ b/indra/newview/llfavoritesbar.h
@@ -141,7 +141,7 @@ private:
* inserts an item identified by insertedItemId BEFORE an item identified by beforeItemId.
* this function assumes that an item identified by insertedItemId doesn't exist in items array.
*/
- void insertBeforeItem(LLInventoryModel::item_array_t& items, const LLUUID& beforeItemId, const LLUUID& insertedItemId);
+ void insertBeforeItem(LLInventoryModel::item_array_t& items, const LLUUID& beforeItemId, LLViewerInventoryItem* insertedItem);
// finds an item by it's UUID in the items array
LLInventoryModel::item_array_t::iterator findItemByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id);
diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp
index 92ad28a105..63ea990d14 100644
--- a/indra/newview/llfloaterabout.cpp
+++ b/indra/newview/llfloaterabout.cpp
@@ -61,6 +61,9 @@
#include "lluri.h"
#include "v3dmath.h"
#include "llwindow.h"
+#include "stringize.h"
+#include "llsdutil_math.h"
+#include "lleventdispatcher.h"
#if LL_WINDOWS
#include "lldxhardware.h"
@@ -85,6 +88,10 @@ private:
public:
/*virtual*/ BOOL postBuild();
+
+ /// Obtain the data used to fill out the contents string. This is
+ /// separated so that we can programmatically access the same info.
+ static LLSD getInfo();
void onClickCopyToClipboard();
};
@@ -114,25 +121,117 @@ BOOL LLFloaterAbout::postBuild()
getChild<LLUICtrl>("copy_btn")->setCommitCallback(
boost::bind(&LLFloaterAbout::onClickCopyToClipboard, this));
- // Version string
- std::string version = LLTrans::getString("APP_NAME")
- + llformat(" %d.%d.%d (%d) %s %s (%s)\n",
- LL_VERSION_MAJOR, LL_VERSION_MINOR, LL_VERSION_PATCH, LL_VIEWER_BUILD,
- __DATE__, __TIME__,
- gSavedSettings.getString("VersionChannelName").c_str());
+#if LL_WINDOWS
+ getWindow()->incBusyCount();
+ getWindow()->setCursor(UI_CURSOR_ARROW);
+#endif
+ LLSD info(getInfo());
+#if LL_WINDOWS
+ getWindow()->decBusyCount();
+ getWindow()->setCursor(UI_CURSOR_ARROW);
+#endif
- std::string support;
- support.append(version);
- support.append("[" + get_viewer_release_notes_url() + " " +
- LLTrans::getString("ReleaseNotes") + "]");
- support.append("\n\n");
+ std::ostringstream support;
-#if LL_MSVC
- support.append(llformat("Built with MSVC version %d\n\n", _MSC_VER));
-#endif
+ // Render the LLSD from getInfo() as a format_map_t
+ LLStringUtil::format_map_t args;
+ // For reasons I don't yet understand, [ReleaseNotes] is not part of the
+ // default substitution strings whereas [APP_NAME] is. But it works to
+ // simply copy it into these specific args.
+ args["ReleaseNotes"] = LLTrans::getString("ReleaseNotes");
+ for (LLSD::map_const_iterator ii(info.beginMap()), iend(info.endMap());
+ ii != iend; ++ii)
+ {
+ if (! ii->second.isArray())
+ {
+ // Scalar value
+ if (ii->second.isUndefined())
+ {
+ args[ii->first] = getString("none");
+ }
+ else
+ {
+ // don't forget to render value asString()
+ args[ii->first] = ii->second.asString();
+ }
+ }
+ else
+ {
+ // array value: build KEY_0, KEY_1 etc. entries
+ for (LLSD::Integer n(0), size(ii->second.size()); n < size; ++n)
+ {
+ args[STRINGIZE(ii->first << '_' << n)] = ii->second[n].asString();
+ }
+ }
+ }
+
+ // Now build the various pieces
+ support << getString("AboutHeader", args);
+ if (info.has("COMPILER"))
+ {
+ support << "\n\n" << getString("AboutCompiler", args);
+ }
+ if (info.has("REGION"))
+ {
+ support << "\n\n" << getString("AboutPosition", args);
+ }
+ support << "\n\n" << getString("AboutSystem", args);
+ if (info.has("GRAPHICS_DRIVER_VERSION"))
+ {
+ support << "\n\n" << getString("AboutDriver", args);
+ }
+ support << "\n\n" << getString("AboutLibs", args);
+ if (info.has("PACKETS_IN"))
+ {
+ support << '\n' << getString("AboutTraffic", args);
+ }
-#if LL_GNUC
- support.append(llformat("Built with GCC version %d\n\n", GCC_VERSION));
+ support_widget->appendText(support.str(),
+ FALSE,
+ LLStyle::Params()
+ .color(LLUIColorTable::instance().getColor("TextFgReadOnlyColor")));
+ support_widget->blockUndo();
+
+ // Fix views
+ support_widget->setCursorPos(0);
+ support_widget->setEnabled(FALSE);
+
+ credits_widget->setCursorPos(0);
+ credits_widget->setEnabled(FALSE);
+
+ return TRUE;
+}
+
+// static
+LLSD LLFloaterAbout::getInfo()
+{
+ // The point of having one method build an LLSD info block and the other
+ // construct the user-visible About string is to ensure that the same info
+ // is available to a getInfo() caller as to the user opening
+ // LLFloaterAbout.
+ LLSD info;
+ LLSD version;
+ version.append(LL_VERSION_MAJOR);
+ version.append(LL_VERSION_MINOR);
+ version.append(LL_VERSION_PATCH);
+ version.append(LL_VERSION_BUILD);
+ info["VIEWER_VERSION"] = version;
+ info["VIEWER_VERSION_STR"] = STRINGIZE(version[0].asInteger() << '.' <<
+ version[1].asInteger() << '.' <<
+ version[2].asInteger() << '.' <<
+ version[3].asInteger());
+ info["BUILD_DATE"] = __DATE__;
+ info["BUILD_TIME"] = __TIME__;
+ info["CHANNEL"] = gSavedSettings.getString("VersionChannelName");
+
+ info["VIEWER_RELEASE_NOTES_URL"] = get_viewer_release_notes_url();
+
+#if LL_MSVC
+ info["COMPILER"] = "MSVC";
+ info["COMPILER_VERSION"] = _MSC_VER;
+#elif LL_GNUC
+ info["COMPILER"] = "GCC";
+ info["COMPILER_VERSION"] = GCC_VERSION;
#endif
// Position
@@ -140,120 +239,49 @@ BOOL LLFloaterAbout::postBuild()
if (region)
{
const LLVector3d &pos = gAgent.getPositionGlobal();
- LLUIString pos_text = getString("you_are_at");
- pos_text.setArg("[POSITION]",
- llformat("%.1f, %.1f, %.1f ", pos.mdV[VX], pos.mdV[VY], pos.mdV[VZ]));
- support.append(pos_text);
-
- LLUIString region_text = getString ("in_region") + " ";
- region_text.setArg("[REGION]", llformat ("%s", gAgent.getRegion()->getName().c_str()));
- support.append(region_text);
-
- std::string buffer;
- buffer = gAgent.getRegion()->getHost().getHostName();
- support.append(buffer);
- support.append(" (");
- buffer = gAgent.getRegion()->getHost().getString();
- support.append(buffer);
- support.append(")\n");
- support.append(gLastVersionChannel);
- support.append("\n");
- support.append("[" + LLWeb::escapeURL(region->getCapability("ServerReleaseNotes")) +
- " " + LLTrans::getString("ReleaseNotes") + "]");
- support.append("\n\n");
+ info["POSITION"] = ll_sd_from_vector3d(pos);
+ info["REGION"] = gAgent.getRegion()->getName();
+ info["HOSTNAME"] = gAgent.getRegion()->getHost().getHostName();
+ info["HOSTIP"] = gAgent.getRegion()->getHost().getString();
+ info["SERVER_VERSION"] = gLastVersionChannel;
+ info["SERVER_RELEASE_NOTES_URL"] = LLWeb::escapeURL(region->getCapability("ServerReleaseNotes"));
}
- // *NOTE: Do not translate text like GPU, Graphics Card, etc -
- // Most PC users that know what these mean will be used to the english versions,
- // and this info sometimes gets sent to support
-
// CPU
- support.append(getString("CPU") + " ");
- support.append( gSysCPU.getCPUString() );
- support.append("\n");
-
- U32 memory = gSysMemory.getPhysicalMemoryKB() / 1024;
+ info["CPU"] = gSysCPU.getCPUString();
+ info["MEMORY_MB"] = LLSD::Integer(gSysMemory.getPhysicalMemoryKB() / 1024);
// Moved hack adjustment to Windows memory size into llsys.cpp
-
- LLStringUtil::format_map_t args;
- args["[MEM]"] = llformat ("%u", memory);
- support.append(getString("Memory", args) + "\n");
-
- support.append(getString("OSVersion") + " ");
- support.append( LLAppViewer::instance()->getOSInfo().getOSString() );
- support.append("\n");
-
- support.append(getString("GraphicsCardVendor") + " ");
- support.append( (const char*) glGetString(GL_VENDOR) );
- support.append("\n");
-
- support.append(getString("GraphicsCard") + " ");
- support.append( (const char*) glGetString(GL_RENDERER) );
- support.append("\n");
+ info["OS_VERSION"] = LLAppViewer::instance()->getOSInfo().getOSString();
+ info["GRAPHICS_CARD_VENDOR"] = (const char*)(glGetString(GL_VENDOR));
+ info["GRAPHICS_CARD"] = (const char*)(glGetString(GL_RENDERER));
#if LL_WINDOWS
- getWindow()->incBusyCount();
- getWindow()->setCursor(UI_CURSOR_ARROW);
- support.append("Windows Graphics Driver Version: ");
LLSD driver_info = gDXHardware.getDisplayInfo();
if (driver_info.has("DriverVersion"))
{
- support.append(driver_info["DriverVersion"]);
+ info["GRAPHICS_DRIVER_VERSION"] = driver_info["DriverVersion"];
}
- support.append("\n");
- getWindow()->decBusyCount();
- getWindow()->setCursor(UI_CURSOR_ARROW);
#endif
- support.append(getString("OpenGLVersion") + " ");
- support.append( (const char*) glGetString(GL_VERSION) );
- support.append("\n");
-
- support.append("\n");
-
- support.append(getString("LibCurlVersion") + " ");
- support.append( LLCurl::getVersionString() );
- support.append("\n");
-
- support.append(getString("J2CDecoderVersion") + " ");
- support.append( LLImageJ2C::getEngineInfo() );
- support.append("\n");
-
- support.append(getString("AudioDriverVersion") + " ");
+ info["OPENGL_VERSION"] = (const char*)(glGetString(GL_VERSION));
+ info["LIBCURL_VERSION"] = LLCurl::getVersionString();
+ info["J2C_VERSION"] = LLImageJ2C::getEngineInfo();
bool want_fullname = true;
- support.append( gAudiop ? gAudiop->getDriverName(want_fullname) : getString("none") );
- support.append("\n");
+ info["AUDIO_DRIVER_VERSION"] = gAudiop ? LLSD(gAudiop->getDriverName(want_fullname)) : LLSD();
// TODO: Implement media plugin version query
-
- support.append(getString("LLQtWebkitVersion") + " ");
- support.append("\n");
+ info["QT_WEBKIT_VERSION"] = "4.5.2";
if (gPacketsIn > 0)
{
- args["[LOST]"] = llformat ("%.0f", LLViewerStats::getInstance()->mPacketsLostStat.getCurrent());
- args["[IN]"] = llformat ("%.0f", F32(gPacketsIn));
- args["[PCT]"] = llformat ("%.1f", 100.f*LLViewerStats::getInstance()->mPacketsLostStat.getCurrent() / F32(gPacketsIn) );
- support.append(getString ("PacketsLost", args) + "\n");
+ info["PACKETS_LOST"] = LLViewerStats::getInstance()->mPacketsLostStat.getCurrent();
+ info["PACKETS_IN"] = F32(gPacketsIn);
+ info["PACKETS_PCT"] = 100.f*info["PACKETS_LOST"].asReal() / info["PACKETS_IN"].asReal();
}
- support_widget->appendText(support,
- FALSE,
- LLStyle::Params()
- .color(LLUIColorTable::instance().getColor("TextFgReadOnlyColor")));
- support_widget->blockUndo();
-
- // Fix views
- support_widget->setCursorPos(0);
- support_widget->setEnabled(FALSE);
-
- credits_widget->setCursorPos(0);
- credits_widget->setEnabled(FALSE);
-
- return TRUE;
+ return info;
}
-
static std::string get_viewer_release_notes_url()
{
std::ostringstream version;
@@ -272,6 +300,27 @@ static std::string get_viewer_release_notes_url()
return LLWeb::escapeURL(url.str());
}
+class LLFloaterAboutListener: public LLDispatchListener
+{
+public:
+ LLFloaterAboutListener():
+ LLDispatchListener("LLFloaterAbout", "op")
+ {
+ add("getInfo", &LLFloaterAboutListener::getInfo, LLSD().insert("reply", LLSD()));
+ }
+
+private:
+ void getInfo(const LLSD& request) const
+ {
+ LLReqID reqid(request);
+ LLSD reply(LLFloaterAbout::getInfo());
+ reqid.stamp(reply);
+ LLEventPumps::instance().obtain(request["reply"]).post(reply);
+ }
+};
+
+static LLFloaterAboutListener floaterAboutListener;
+
void LLFloaterAbout::onClickCopyToClipboard()
{
LLViewerTextEditor *support_widget =
diff --git a/indra/newview/llfloaterchat.cpp b/indra/newview/llfloaterchat.cpp
index 86abebe7ce..ed14079ae9 100644
--- a/indra/newview/llfloaterchat.cpp
+++ b/indra/newview/llfloaterchat.cpp
@@ -182,13 +182,7 @@ void add_timestamped_line(LLViewerTextEditor* edit, LLChat chat, const LLColor4&
void log_chat_text(const LLChat& chat)
{
- std::string histstr;
- if (gSavedPerAccountSettings.getBOOL("LogTimestamp"))
- histstr = LLLogChat::timestamp(gSavedPerAccountSettings.getBOOL("LogTimestampDate")) + chat.mText;
- else
- histstr = chat.mText;
-
- LLLogChat::saveHistory(std::string("chat"),histstr);
+ LLLogChat::saveHistory(std::string("chat"), chat.mFromName, chat.mFromID, chat.mText);
}
// static
void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file)
@@ -476,7 +470,7 @@ void LLFloaterChat::loadHistory()
}
//static
-void LLFloaterChat::chatFromLogFile(LLLogChat::ELogLineType type , std::string line, void* userdata)
+void LLFloaterChat::chatFromLogFile(LLLogChat::ELogLineType type , const LLSD& line, void* userdata)
{
switch (type)
{
@@ -485,9 +479,10 @@ void LLFloaterChat::chatFromLogFile(LLLogChat::ELogLineType type , std::string l
// *TODO: nice message from XML file here
break;
case LLLogChat::LOG_LINE:
+ case LLLogChat::LOG_LLSD:
{
LLChat chat;
- chat.mText = line;
+ chat.mText = line["message"].asString();
get_text_color(chat);
addChatHistory(chat, FALSE);
}
diff --git a/indra/newview/llfloaterchat.h b/indra/newview/llfloaterchat.h
index 6ba3165d6a..aed82a6781 100644
--- a/indra/newview/llfloaterchat.h
+++ b/indra/newview/llfloaterchat.h
@@ -78,7 +78,7 @@ public:
static void onClickMute(void *data);
static void onClickToggleShowMute(LLUICtrl* caller, void *data);
static void onClickToggleActiveSpeakers(void* userdata);
- static void chatFromLogFile(LLLogChat::ELogLineType type,std::string line, void* userdata);
+ static void chatFromLogFile(LLLogChat::ELogLineType type, const LLSD& line, void* userdata);
static void loadHistory();
static void* createSpeakersPanel(void* data);
static void* createChatPanel(void* data);
diff --git a/indra/newview/llfloaterchatterbox.cpp b/indra/newview/llfloaterchatterbox.cpp
index dea656b0e4..fbf09207fe 100644
--- a/indra/newview/llfloaterchatterbox.cpp
+++ b/indra/newview/llfloaterchatterbox.cpp
@@ -42,7 +42,7 @@
#include "llfloaterfriends.h"
#include "llfloatergroups.h"
#include "llviewercontrol.h"
-#include "llimview.h"
+#include "llvoicechannel.h"
#include "llimpanel.h"
//
diff --git a/indra/newview/llfloaterinventory.cpp b/indra/newview/llfloaterinventory.cpp
index c890f9f122..a47916b7d7 100644
--- a/indra/newview/llfloaterinventory.cpp
+++ b/indra/newview/llfloaterinventory.cpp
@@ -1438,7 +1438,11 @@ void LLInventoryPanel::modelChanged(U32 mask)
}
LLFolderViewFolder* new_parent = (LLFolderViewFolder*)mFolders->getItemByID(model_item->getParentUUID());
- if (view_item->getParentFolder() != new_parent)
+
+ // added check against NULL for cases when Inventory panel contains startFolder.
+ // in this case parent is LLFolderView (LLInventoryPanel::mFolders) itself.
+ // this check is a fix for bug EXT-1859.
+ if (NULL != new_parent && view_item->getParentFolder() != new_parent)
{
view_item->getParentFolder()->extractItem(view_item);
view_item->addToFolder(new_parent, mFolders);
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index dbee9ea309..8b3391726a 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -843,10 +843,7 @@ void LLFloaterPreference::refreshEnabledState()
bool bumpshiny = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps && LLFeatureManager::getInstance()->isFeatureAvailable("RenderObjectBump");
getChild<LLCheckBoxCtrl>("BumpShiny")->setEnabled(bumpshiny ? TRUE : FALSE);
- for (S32 i = 0; i < radio_reflection_detail->getItemCount(); ++i)
- {
- radio_reflection_detail->setIndexEnabled(i, ctrl_reflections->get() && reflections);
- }
+ radio_reflection_detail->setEnabled(ctrl_reflections->get() && reflections);
// Avatar Mode
// Enable Avatar Shaders
@@ -880,20 +877,10 @@ void LLFloaterPreference::refreshEnabledState()
{
mRadioTerrainDetail->setValue(1);
mRadioTerrainDetail->setEnabled(FALSE);
- for (S32 i = 0; i < mRadioTerrainDetail->getItemCount(); ++i)
- {
- mRadioTerrainDetail->setIndexEnabled(i, FALSE);
- }
}
else
{
- mRadioTerrainDetail->setEnabled(TRUE);
-
- for (S32 i = 0; i < mRadioTerrainDetail->getItemCount(); ++i)
- {
- mRadioTerrainDetail->setIndexEnabled(i, TRUE);
- }
-
+ mRadioTerrainDetail->setEnabled(TRUE);
}
// WindLight
diff --git a/indra/newview/llfloatervoicedevicesettings.cpp b/indra/newview/llfloatervoicedevicesettings.cpp
index b64257b11d..aca9198f59 100644
--- a/indra/newview/llfloatervoicedevicesettings.cpp
+++ b/indra/newview/llfloatervoicedevicesettings.cpp
@@ -43,7 +43,7 @@
#include "llsliderctrl.h"
#include "llviewercontrol.h"
#include "llvoiceclient.h"
-#include "llimpanel.h"
+#include "llvoicechannel.h"
// Library includes (after viewer)
#include "lluictrlfactory.h"
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index a20b5ea66c..f3fec70ac9 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -42,7 +42,6 @@
#include "llchiclet.h"
#include "llfloaterchat.h"
#include "llfloaterreg.h"
-#include "llimview.h"
#include "lllineeditor.h"
#include "lllogchat.h"
#include "llpanelimcontrolpanel.h"
@@ -50,6 +49,7 @@
#include "lltrans.h"
#include "llchathistory.h"
#include "llviewerwindow.h"
+#include "llvoicechannel.h"
#include "lltransientfloatermgr.h"
@@ -61,7 +61,14 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)
mLastMessageIndex(-1),
mDialog(IM_NOTHING_SPECIAL),
mChatHistory(NULL),
- mInputEditor(NULL),
+ mInputEditor(NULL),
+ mSavedTitle(),
+ mTypingStart(),
+ mShouldSendTypingState(false),
+ mMeTyping(false),
+ mOtherTyping(false),
+ mTypingTimer(),
+ mTypingTimeoutTimer(),
mPositioned(false),
mSessionInitialized(false)
{
@@ -71,12 +78,15 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)
mSessionInitialized = im_session->mSessionInitialized;
mDialog = im_session->mType;
- if (IM_NOTHING_SPECIAL == mDialog || IM_SESSION_P2P_INVITE == mDialog)
- {
+ switch(mDialog){
+ case IM_NOTHING_SPECIAL:
+ case IM_SESSION_P2P_INVITE:
mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelIMControl, this);
- }
- else
- {
+ break;
+ case IM_SESSION_CONFERENCE_START:
+ mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelAdHocControl, this);
+ break;
+ default:
mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this);
}
}
@@ -95,6 +105,7 @@ void LLIMFloater::onFocusReceived()
// virtual
void LLIMFloater::onClose(bool app_quitting)
{
+ setTyping(false);
gIMMgr->leaveSession(mSessionID);
}
@@ -141,6 +152,7 @@ void LLIMFloater::onSendMsg( LLUICtrl* ctrl, void* userdata )
{
LLIMFloater* self = (LLIMFloater*) userdata;
self->sendMsg();
+ self->setTyping(false);
}
void LLIMFloater::sendMsg()
@@ -193,9 +205,10 @@ BOOL LLIMFloater::postBuild()
if (other_party_id.notNull())
{
mOtherParticipantUUID = other_party_id;
- mControlPanel->setID(mOtherParticipantUUID);
}
+ mControlPanel->setSessionId(mSessionID);
+
LLButton* slide_left = getChild<LLButton>("slide_left_btn");
slide_left->setVisible(mControlPanel->getVisible());
slide_left->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this));
@@ -222,10 +235,16 @@ BOOL LLIMFloater::postBuild()
setTitle(LLIMModel::instance().getName(mSessionID));
setDocked(true);
-
- if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") )
+
+ mTypingStart = LLTrans::getString("IM_typing_start_string");
+
+ // Disable input editor if session cannot accept text
+ LLIMModel::LLIMSession* im_session =
+ LLIMModel::instance().findIMSession(mSessionID);
+ if( im_session && !im_session->mTextIMPossible )
{
- LLLogChat::loadHistory(getTitle(), &chatFromLogFile, (void *)this);
+ mInputEditor->setEnabled(FALSE);
+ mInputEditor->setLabel(LLTrans::getString("IM_unavailable_text_label"));
}
//*TODO if session is not initialized yet, add some sort of a warning message like "starting session...blablabla"
@@ -234,6 +253,20 @@ BOOL LLIMFloater::postBuild()
return LLDockableFloater::postBuild();
}
+// virtual
+void LLIMFloater::draw()
+{
+ if ( mMeTyping )
+ {
+ // Time out if user hasn't typed for a while.
+ if ( mTypingTimeoutTimer.getElapsedTimeF32() > LLAgent::TYPING_TIMEOUT_SECS )
+ {
+ setTyping(false);
+ }
+ }
+
+ LLFloater::draw();
+}
// static
@@ -255,6 +288,15 @@ void* LLIMFloater::createPanelGroupControl(void* userdata)
return self->mControlPanel;
}
+// static
+void* LLIMFloater::createPanelAdHocControl(void* userdata)
+{
+ LLIMFloater *self = (LLIMFloater*)userdata;
+ self->mControlPanel = new LLPanelAdHocControlPanel(self->mSessionID);
+ self->mControlPanel->setXMLFilename("panel_adhoc_control_panel.xml");
+ return self->mControlPanel;
+}
+
void LLIMFloater::onSlide()
{
LLPanel* im_control_panel = getChild<LLPanel>("panel_im_control_panel");
@@ -379,10 +421,12 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id)
{
mSessionInitialized = true;
+ //will be different only for an ad-hoc im session
if (mSessionID != im_session_id)
{
mSessionID = im_session_id;
setKey(im_session_id);
+ mControlPanel->setSessionId(im_session_id);
}
//*TODO here we should remove "starting session..." warning message if we added it in postBuild() (IB)
@@ -402,10 +446,8 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id)
void LLIMFloater::updateMessages()
{
- std::list<LLSD> messages = LLIMModel::instance().getMessages(mSessionID, mLastMessageIndex+1);
- std::string agent_name;
-
- gCacheName->getFullName(gAgentID, agent_name);
+ std::list<LLSD> messages;
+ LLIMModel::instance().getMessages(mSessionID, messages, mLastMessageIndex+1);
if (messages.size())
{
@@ -414,21 +456,22 @@ void LLIMFloater::updateMessages()
std::ostringstream message;
std::list<LLSD>::const_reverse_iterator iter = messages.rbegin();
std::list<LLSD>::const_reverse_iterator iter_end = messages.rend();
- for (; iter != iter_end; ++iter)
+ for (; iter != iter_end; ++iter)
{
LLSD msg = *iter;
- std::string from = msg["from"].asString();
std::string time = msg["time"].asString();
LLUUID from_id = msg["from_id"].asUUID();
+ std::string from = from_id != gAgentID ? msg["from"].asString() : LLTrans::getString("You");
std::string message = msg["message"].asString();
LLStyle::Params style_params;
style_params.color(chat_color);
- if (from == agent_name)
- from = LLTrans::getString("You");
+ LLChat chat(message);
+ chat.mFromID = from_id;
+ chat.mFromName = from;
- mChatHistory->appendWidgetMessage(from_id, from, time, message, style_params);
+ mChatHistory->appendWidgetMessage(chat, style_params);
mLastMessageIndex = msg["index"].asInteger();
}
@@ -440,9 +483,14 @@ void LLIMFloater::onInputEditorFocusReceived( LLFocusableElement* caller, void*
{
LLIMFloater* self= (LLIMFloater*) userdata;
- //in disconnected state IM input editor should be disabled
- self->mInputEditor->setEnabled(!gDisconnected);
-
+ // Allow enabling the LLIMFloater input editor only if session can accept text
+ LLIMModel::LLIMSession* im_session =
+ LLIMModel::instance().findIMSession(self->mSessionID);
+ if( im_session && im_session->mTextIMPossible )
+ {
+ //in disconnected state IM input editor should be disabled
+ self->mInputEditor->setEnabled(!gDisconnected);
+ }
self->mChatHistory->setCursorAndScrollToEnd();
}
@@ -450,7 +498,7 @@ void LLIMFloater::onInputEditorFocusReceived( LLFocusableElement* caller, void*
void LLIMFloater::onInputEditorFocusLost(LLFocusableElement* caller, void* userdata)
{
LLIMFloater* self = (LLIMFloater*) userdata;
- self->setTyping(FALSE);
+ self->setTyping(false);
}
// static
@@ -460,53 +508,141 @@ void LLIMFloater::onInputEditorKeystroke(LLLineEditor* caller, void* userdata)
std::string text = self->mInputEditor->getText();
if (!text.empty())
{
- self->setTyping(TRUE);
+ self->setTyping(true);
}
else
{
// Deleting all text counts as stopping typing.
- self->setTyping(FALSE);
+ self->setTyping(false);
}
}
-
-//just a stub for now
-void LLIMFloater::setTyping(BOOL typing)
+void LLIMFloater::setTyping(bool typing)
{
+ if ( typing )
+ {
+ // Started or proceeded typing, reset the typing timeout timer
+ mTypingTimeoutTimer.reset();
+ }
+
+ if ( mMeTyping != typing )
+ {
+ // Typing state is changed
+ mMeTyping = typing;
+ // So, should send current state
+ mShouldSendTypingState = true;
+ // In case typing is started, send state after some delay
+ mTypingTimer.reset();
+ }
+
+ // Don't want to send typing indicators to multiple people, potentially too
+ // much network traffic. Only send in person-to-person IMs.
+ if ( mShouldSendTypingState && mDialog == IM_NOTHING_SPECIAL )
+ {
+ if ( mMeTyping )
+ {
+ if ( mTypingTimer.getElapsedTimeF32() > 1.f )
+ {
+ // Still typing, send 'start typing' notification
+ LLIMModel::instance().sendTypingState(mSessionID, mOtherParticipantUUID, TRUE);
+ mShouldSendTypingState = false;
+ }
+ }
+ else
+ {
+ // Send 'stop typing' notification immediately
+ LLIMModel::instance().sendTypingState(mSessionID, mOtherParticipantUUID, FALSE);
+ mShouldSendTypingState = false;
+ }
+ }
+
+ LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
+ if (speaker_mgr)
+ speaker_mgr->setSpeakerTyping(gAgent.getID(), FALSE);
+
}
-void LLIMFloater::chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata)
+void LLIMFloater::processIMTyping(const LLIMInfo* im_info, BOOL typing)
{
- if (!userdata) return;
+ if ( typing )
+ {
+ // other user started typing
+ addTypingIndicator(im_info);
+ }
+ else
+ {
+ // other user stopped typing
+ removeTypingIndicator(im_info);
+ }
+}
- LLIMFloater* self = (LLIMFloater*) userdata;
- std::string message = line;
- S32 im_log_option = gSavedPerAccountSettings.getS32("IMLogOptions");
- switch (type)
+void LLIMFloater::processSessionUpdate(const LLSD& session_update)
+{
+ // *TODO : verify following code when moderated mode will be implemented
+ if ( false && session_update.has("moderated_mode") &&
+ session_update["moderated_mode"].has("voice") )
{
- case LLLogChat::LOG_EMPTY:
- // add warning log enabled message
- if (im_log_option!=LOG_CHAT)
+ BOOL voice_moderated = session_update["moderated_mode"]["voice"];
+ const std::string session_label = LLIMModel::instance().getName(mSessionID);
+
+ if (voice_moderated)
{
- message = LLTrans::getString("IM_logging_string");
+ setTitle(session_label + std::string(" ") + LLTrans::getString("IM_moderated_chat_label"));
}
- break;
- case LLLogChat::LOG_END:
- // add log end message
- if (im_log_option!=LOG_CHAT)
+ else
+ {
+ setTitle(session_label);
+ }
+
+ // *TODO : uncomment this when/if LLPanelActiveSpeakers panel will be added
+ //update the speakers dropdown too
+ //mSpeakerPanel->setVoiceModerationCtrlMode(voice_moderated);
+ }
+}
+
+void LLIMFloater::addTypingIndicator(const LLIMInfo* im_info)
+{
+ // We may have lost a "stop-typing" packet, don't add it twice
+ if ( im_info && !mOtherTyping )
+ {
+ mOtherTyping = true;
+
+ // Create typing is started title string
+ LLUIString typing_start(mTypingStart);
+ typing_start.setArg("[NAME]", im_info->mName);
+
+ // Save and set new title
+ mSavedTitle = getTitle();
+ setTitle (typing_start);
+
+ // Update speaker
+ LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
+ if ( speaker_mgr )
{
- message = LLTrans::getString("IM_logging_string");
+ speaker_mgr->setSpeakerTyping(im_info->mFromID, TRUE);
}
- break;
- case LLLogChat::LOG_LINE:
- // just add normal lines from file
- break;
- default:
- // nothing
- break;
}
+}
- self->mChatHistory->appendText(message, true, LLStyle::Params().color(LLUIColorTable::instance().getColor("ChatHistoryTextColor")));
- self->mChatHistory->blockUndo();
+void LLIMFloater::removeTypingIndicator(const LLIMInfo* im_info)
+{
+ if ( mOtherTyping )
+ {
+ mOtherTyping = false;
+
+ // Revert the title to saved one
+ setTitle(mSavedTitle);
+
+ if ( im_info )
+ {
+ // Update speaker
+ LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
+ if ( speaker_mgr )
+ {
+ speaker_mgr->setSpeakerTyping(im_info->mFromID, FALSE);
+ }
+ }
+
+ }
}
diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h
index 99810b6d6d..d2aac57ee2 100644
--- a/indra/newview/llimfloater.h
+++ b/indra/newview/llimfloater.h
@@ -55,6 +55,8 @@ public:
// LLView overrides
/*virtual*/ BOOL postBuild();
/*virtual*/ void setVisible(BOOL visible);
+ // Check typing timeout timer.
+ /*virtual*/ void draw();
// LLFloater overrides
/*virtual*/ void onClose(bool app_quitting);
@@ -85,6 +87,8 @@ public:
void setPositioned(bool b) { mPositioned = b; };
void onVisibilityChange(const LLSD& new_visibility);
+ void processIMTyping(const LLIMInfo* im_info, BOOL typing);
+ void processSessionUpdate(const LLSD& session_update);
private:
// process focus events to set a currently active session
@@ -94,15 +98,19 @@ private:
static void onInputEditorFocusReceived( LLFocusableElement* caller, void* userdata );
static void onInputEditorFocusLost(LLFocusableElement* caller, void* userdata);
static void onInputEditorKeystroke(LLLineEditor* caller, void* userdata);
- void setTyping(BOOL typing);
+ void setTyping(bool typing);
void onSlide();
static void* createPanelIMControl(void* userdata);
static void* createPanelGroupControl(void* userdata);
+ static void* createPanelAdHocControl(void* userdata);
// gets a rect that bounds possible positions for the LLIMFloater on a screen (EXT-1111)
void getAllowedRect(LLRect& rect);
- static void chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata);
+ // Add the "User is typing..." indicator.
+ void addTypingIndicator(const LLIMInfo* im_info);
+ // Remove the "User is typing..." indicator.
+ void removeTypingIndicator(const LLIMInfo* im_info = NULL);
LLPanelChatControlPanel* mControlPanel;
LLUUID mSessionID;
@@ -114,6 +122,14 @@ private:
LLLineEditor* mInputEditor;
bool mPositioned;
+ std::string mSavedTitle;
+ LLUIString mTypingStart;
+ bool mMeTyping;
+ bool mOtherTyping;
+ bool mShouldSendTypingState;
+ LLFrameTimer mTypingTimer;
+ LLFrameTimer mTypingTimeoutTimer;
+
bool mSessionInitialized;
LLSD mQueuedMsgsForInit;
};
diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp
index 163984f740..c4beb666ea 100644
--- a/indra/newview/llimpanel.cpp
+++ b/indra/newview/llimpanel.cpp
@@ -54,6 +54,7 @@
#include "llconsole.h"
#include "llgroupactions.h"
#include "llfloater.h"
+#include "llfloateractivespeakers.h"
#include "llfloatercall.h"
#include "llavataractions.h"
#include "llimview.h"
@@ -77,6 +78,7 @@
#include "llviewercontrol.h"
#include "lluictrlfactory.h"
#include "llviewerwindow.h"
+#include "llvoicechannel.h"
#include "lllogchat.h"
#include "llweb.h"
#include "llhttpclient.h"
@@ -90,7 +92,6 @@
const S32 LINE_HEIGHT = 16;
const S32 MIN_WIDTH = 200;
const S32 MIN_HEIGHT = 130;
-const U32 DEFAULT_RETRIES_COUNT = 3;
//
// Statics
@@ -100,831 +101,6 @@ static std::string sTitleString = "Instant Message with [NAME]";
static std::string sTypingStartString = "[NAME]: ...";
static std::string sSessionStartString = "Starting session with [NAME] please wait.";
-LLVoiceChannel::voice_channel_map_t LLVoiceChannel::sVoiceChannelMap;
-LLVoiceChannel::voice_channel_map_uri_t LLVoiceChannel::sVoiceChannelURIMap;
-LLVoiceChannel* LLVoiceChannel::sCurrentVoiceChannel = NULL;
-LLVoiceChannel* LLVoiceChannel::sSuspendedVoiceChannel = NULL;
-
-BOOL LLVoiceChannel::sSuspended = FALSE;
-
-
-
-class LLVoiceCallCapResponder : public LLHTTPClient::Responder
-{
-public:
- LLVoiceCallCapResponder(const LLUUID& session_id) : mSessionID(session_id) {};
-
- virtual void error(U32 status, const std::string& reason); // called with bad status codes
- virtual void result(const LLSD& content);
-
-private:
- LLUUID mSessionID;
-};
-
-
-void LLVoiceCallCapResponder::error(U32 status, const std::string& reason)
-{
- llwarns << "LLVoiceCallCapResponder::error("
- << status << ": " << reason << ")"
- << llendl;
- LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID);
- if ( channelp )
- {
- if ( 403 == status )
- {
- //403 == no ability
- LLNotifications::instance().add(
- "VoiceNotAllowed",
- channelp->getNotifyArgs());
- }
- else
- {
- LLNotifications::instance().add(
- "VoiceCallGenericError",
- channelp->getNotifyArgs());
- }
- channelp->deactivate();
- }
-}
-
-void LLVoiceCallCapResponder::result(const LLSD& content)
-{
- LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID);
- if (channelp)
- {
- //*TODO: DEBUG SPAM
- LLSD::map_const_iterator iter;
- for(iter = content.beginMap(); iter != content.endMap(); ++iter)
- {
- llinfos << "LLVoiceCallCapResponder::result got "
- << iter->first << llendl;
- }
-
- channelp->setChannelInfo(
- content["voice_credentials"]["channel_uri"].asString(),
- content["voice_credentials"]["channel_credentials"].asString());
- }
-}
-
-//
-// LLVoiceChannel
-//
-LLVoiceChannel::LLVoiceChannel(const LLUUID& session_id, const std::string& session_name) :
- mSessionID(session_id),
- mState(STATE_NO_CHANNEL_INFO),
- mSessionName(session_name),
- mIgnoreNextSessionLeave(FALSE)
-{
- mNotifyArgs["VOICE_CHANNEL_NAME"] = mSessionName;
-
- if (!sVoiceChannelMap.insert(std::make_pair(session_id, this)).second)
- {
- // a voice channel already exists for this session id, so this instance will be orphaned
- // the end result should simply be the failure to make voice calls
- llwarns << "Duplicate voice channels registered for session_id " << session_id << llendl;
- }
-
- LLVoiceClient::getInstance()->addObserver(this);
-}
-
-LLVoiceChannel::~LLVoiceChannel()
-{
- // Don't use LLVoiceClient::getInstance() here -- this can get called during atexit() time and that singleton MAY have already been destroyed.
- if(gVoiceClient)
- {
- gVoiceClient->removeObserver(this);
- }
-
- sVoiceChannelMap.erase(mSessionID);
- sVoiceChannelURIMap.erase(mURI);
-}
-
-void LLVoiceChannel::setChannelInfo(
- const std::string& uri,
- const std::string& credentials)
-{
- setURI(uri);
-
- mCredentials = credentials;
-
- if (mState == STATE_NO_CHANNEL_INFO)
- {
- if (mURI.empty())
- {
- LLNotifications::instance().add("VoiceChannelJoinFailed", mNotifyArgs);
- llwarns << "Received empty URI for channel " << mSessionName << llendl;
- deactivate();
- }
- else if (mCredentials.empty())
- {
- LLNotifications::instance().add("VoiceChannelJoinFailed", mNotifyArgs);
- llwarns << "Received empty credentials for channel " << mSessionName << llendl;
- deactivate();
- }
- else
- {
- setState(STATE_READY);
-
- // if we are supposed to be active, reconnect
- // this will happen on initial connect, as we request credentials on first use
- if (sCurrentVoiceChannel == this)
- {
- // just in case we got new channel info while active
- // should move over to new channel
- activate();
- }
- }
- }
-}
-
-void LLVoiceChannel::onChange(EStatusType type, const std::string &channelURI, bool proximal)
-{
- if (channelURI != mURI)
- {
- return;
- }
-
- if (type < BEGIN_ERROR_STATUS)
- {
- handleStatusChange(type);
- }
- else
- {
- handleError(type);
- }
-}
-
-void LLVoiceChannel::handleStatusChange(EStatusType type)
-{
- // status updates
- switch(type)
- {
- case STATUS_LOGIN_RETRY:
- //mLoginNotificationHandle = LLNotifyBox::showXml("VoiceLoginRetry")->getHandle();
- LLNotifications::instance().add("VoiceLoginRetry");
- break;
- case STATUS_LOGGED_IN:
- //if (!mLoginNotificationHandle.isDead())
- //{
- // LLNotifyBox* notifyp = (LLNotifyBox*)mLoginNotificationHandle.get();
- // if (notifyp)
- // {
- // notifyp->close();
- // }
- // mLoginNotificationHandle.markDead();
- //}
- break;
- case STATUS_LEFT_CHANNEL:
- if (callStarted() && !mIgnoreNextSessionLeave && !sSuspended)
- {
- // if forceably removed from channel
- // update the UI and revert to default channel
- LLNotifications::instance().add("VoiceChannelDisconnected", mNotifyArgs);
- deactivate();
- }
- mIgnoreNextSessionLeave = FALSE;
- break;
- case STATUS_JOINING:
- if (callStarted())
- {
- setState(STATE_RINGING);
- }
- break;
- case STATUS_JOINED:
- if (callStarted())
- {
- setState(STATE_CONNECTED);
- }
- default:
- break;
- }
-}
-
-// default behavior is to just deactivate channel
-// derived classes provide specific error messages
-void LLVoiceChannel::handleError(EStatusType type)
-{
- deactivate();
- setState(STATE_ERROR);
-}
-
-BOOL LLVoiceChannel::isActive()
-{
- // only considered active when currently bound channel matches what our channel
- return callStarted() && LLVoiceClient::getInstance()->getCurrentChannel() == mURI;
-}
-
-BOOL LLVoiceChannel::callStarted()
-{
- return mState >= STATE_CALL_STARTED;
-}
-
-void LLVoiceChannel::deactivate()
-{
- if (mState >= STATE_RINGING)
- {
- // ignore session leave event
- mIgnoreNextSessionLeave = TRUE;
- }
-
- if (callStarted())
- {
- setState(STATE_HUNG_UP);
- // mute the microphone if required when returning to the proximal channel
- if (gSavedSettings.getBOOL("AutoDisengageMic") && sCurrentVoiceChannel == this)
- {
- gSavedSettings.setBOOL("PTTCurrentlyEnabled", true);
- }
- }
-
- if (sCurrentVoiceChannel == this)
- {
- // default channel is proximal channel
- sCurrentVoiceChannel = LLVoiceChannelProximal::getInstance();
- sCurrentVoiceChannel->activate();
- }
-}
-
-void LLVoiceChannel::activate()
-{
- if (callStarted())
- {
- return;
- }
-
- // deactivate old channel and mark ourselves as the active one
- if (sCurrentVoiceChannel != this)
- {
- // mark as current before deactivating the old channel to prevent
- // activating the proximal channel between IM calls
- LLVoiceChannel* old_channel = sCurrentVoiceChannel;
- sCurrentVoiceChannel = this;
- if (old_channel)
- {
- old_channel->deactivate();
- }
- }
-
- if (mState == STATE_NO_CHANNEL_INFO)
- {
- // responsible for setting status to active
- getChannelInfo();
- }
- else
- {
- setState(STATE_CALL_STARTED);
- }
-}
-
-void LLVoiceChannel::getChannelInfo()
-{
- // pretend we have everything we need
- if (sCurrentVoiceChannel == this)
- {
- setState(STATE_CALL_STARTED);
- }
-}
-
-//static
-LLVoiceChannel* LLVoiceChannel::getChannelByID(const LLUUID& session_id)
-{
- voice_channel_map_t::iterator found_it = sVoiceChannelMap.find(session_id);
- if (found_it == sVoiceChannelMap.end())
- {
- return NULL;
- }
- else
- {
- return found_it->second;
- }
-}
-
-//static
-LLVoiceChannel* LLVoiceChannel::getChannelByURI(std::string uri)
-{
- voice_channel_map_uri_t::iterator found_it = sVoiceChannelURIMap.find(uri);
- if (found_it == sVoiceChannelURIMap.end())
- {
- return NULL;
- }
- else
- {
- return found_it->second;
- }
-}
-
-void LLVoiceChannel::updateSessionID(const LLUUID& new_session_id)
-{
- sVoiceChannelMap.erase(sVoiceChannelMap.find(mSessionID));
- mSessionID = new_session_id;
- sVoiceChannelMap.insert(std::make_pair(mSessionID, this));
-}
-
-void LLVoiceChannel::setURI(std::string uri)
-{
- sVoiceChannelURIMap.erase(mURI);
- mURI = uri;
- sVoiceChannelURIMap.insert(std::make_pair(mURI, this));
-}
-
-void LLVoiceChannel::setState(EState state)
-{
- switch(state)
- {
- case STATE_RINGING:
- gIMMgr->addSystemMessage(mSessionID, "ringing", mNotifyArgs);
- break;
- case STATE_CONNECTED:
- gIMMgr->addSystemMessage(mSessionID, "connected", mNotifyArgs);
- break;
- case STATE_HUNG_UP:
- gIMMgr->addSystemMessage(mSessionID, "hang_up", mNotifyArgs);
- break;
- default:
- break;
- }
-
- mState = state;
-}
-
-void LLVoiceChannel::toggleCallWindowIfNeeded(EState state)
-{
- if (state == STATE_CONNECTED)
- {
- LLFloaterReg::showInstance("voice_call", mSessionID);
- }
- // By checking that current state is CONNECTED we make sure that the call window
- // has been shown, hence there's something to hide. This helps when user presses
- // the "End call" button right after initiating the call.
- // *TODO: move this check to LLFloaterCall?
- else if (state == STATE_HUNG_UP && mState == STATE_CONNECTED)
- {
- LLFloaterReg::hideInstance("voice_call", mSessionID);
- }
-}
-
-//static
-void LLVoiceChannel::initClass()
-{
- sCurrentVoiceChannel = LLVoiceChannelProximal::getInstance();
-}
-
-
-//static
-void LLVoiceChannel::suspend()
-{
- if (!sSuspended)
- {
- sSuspendedVoiceChannel = sCurrentVoiceChannel;
- sSuspended = TRUE;
- }
-}
-
-//static
-void LLVoiceChannel::resume()
-{
- if (sSuspended)
- {
- if (gVoiceClient->voiceEnabled())
- {
- if (sSuspendedVoiceChannel)
- {
- sSuspendedVoiceChannel->activate();
- }
- else
- {
- LLVoiceChannelProximal::getInstance()->activate();
- }
- }
- sSuspended = FALSE;
- }
-}
-
-
-//
-// LLVoiceChannelGroup
-//
-
-LLVoiceChannelGroup::LLVoiceChannelGroup(const LLUUID& session_id, const std::string& session_name) :
- LLVoiceChannel(session_id, session_name)
-{
- mRetries = DEFAULT_RETRIES_COUNT;
- mIsRetrying = FALSE;
-}
-
-void LLVoiceChannelGroup::deactivate()
-{
- if (callStarted())
- {
- LLVoiceClient::getInstance()->leaveNonSpatialChannel();
- }
- LLVoiceChannel::deactivate();
-}
-
-void LLVoiceChannelGroup::activate()
-{
- if (callStarted()) return;
-
- LLVoiceChannel::activate();
-
- if (callStarted())
- {
- // we have the channel info, just need to use it now
- LLVoiceClient::getInstance()->setNonSpatialChannel(
- mURI,
- mCredentials);
-
-#if 0 // *TODO
- if (!gAgent.isInGroup(mSessionID)) // ad-hoc channel
- {
- // Add the party to the list of people with which we've recently interacted.
- for (/*people in the chat*/)
- LLRecentPeople::instance().add(buddy_id);
- }
-#endif
- }
-}
-
-void LLVoiceChannelGroup::getChannelInfo()
-{
- LLViewerRegion* region = gAgent.getRegion();
- if (region)
- {
- std::string url = region->getCapability("ChatSessionRequest");
- LLSD data;
- data["method"] = "call";
- data["session-id"] = mSessionID;
- LLHTTPClient::post(url,
- data,
- new LLVoiceCallCapResponder(mSessionID));
- }
-}
-
-void LLVoiceChannelGroup::setChannelInfo(
- const std::string& uri,
- const std::string& credentials)
-{
- setURI(uri);
-
- mCredentials = credentials;
-
- if (mState == STATE_NO_CHANNEL_INFO)
- {
- if(!mURI.empty() && !mCredentials.empty())
- {
- setState(STATE_READY);
-
- // if we are supposed to be active, reconnect
- // this will happen on initial connect, as we request credentials on first use
- if (sCurrentVoiceChannel == this)
- {
- // just in case we got new channel info while active
- // should move over to new channel
- activate();
- }
- }
- else
- {
- //*TODO: notify user
- llwarns << "Received invalid credentials for channel " << mSessionName << llendl;
- deactivate();
- }
- }
- else if ( mIsRetrying )
- {
- // we have the channel info, just need to use it now
- LLVoiceClient::getInstance()->setNonSpatialChannel(
- mURI,
- mCredentials);
- }
-}
-
-void LLVoiceChannelGroup::handleStatusChange(EStatusType type)
-{
- // status updates
- switch(type)
- {
- case STATUS_JOINED:
- mRetries = 3;
- mIsRetrying = FALSE;
- default:
- break;
- }
-
- LLVoiceChannel::handleStatusChange(type);
-}
-
-void LLVoiceChannelGroup::handleError(EStatusType status)
-{
- std::string notify;
- switch(status)
- {
- case ERROR_CHANNEL_LOCKED:
- case ERROR_CHANNEL_FULL:
- notify = "VoiceChannelFull";
- break;
- case ERROR_NOT_AVAILABLE:
- //clear URI and credentials
- //set the state to be no info
- //and activate
- if ( mRetries > 0 )
- {
- mRetries--;
- mIsRetrying = TRUE;
- mIgnoreNextSessionLeave = TRUE;
-
- getChannelInfo();
- return;
- }
- else
- {
- notify = "VoiceChannelJoinFailed";
- mRetries = DEFAULT_RETRIES_COUNT;
- mIsRetrying = FALSE;
- }
-
- break;
-
- case ERROR_UNKNOWN:
- default:
- break;
- }
-
- // notification
- if (!notify.empty())
- {
- LLNotificationPtr notification = LLNotifications::instance().add(notify, mNotifyArgs);
- // echo to im window
- gIMMgr->addMessage(mSessionID, LLUUID::null, SYSTEM_FROM, notification->getMessage());
- }
-
- LLVoiceChannel::handleError(status);
-}
-
-void LLVoiceChannelGroup::setState(EState state)
-{
- // HACK: Open/close the call window if needed.
- toggleCallWindowIfNeeded(state);
-
- switch(state)
- {
- case STATE_RINGING:
- if ( !mIsRetrying )
- {
- gIMMgr->addSystemMessage(mSessionID, "ringing", mNotifyArgs);
- }
-
- mState = state;
- break;
- default:
- LLVoiceChannel::setState(state);
- }
-}
-
-//
-// LLVoiceChannelProximal
-//
-LLVoiceChannelProximal::LLVoiceChannelProximal() :
- LLVoiceChannel(LLUUID::null, LLStringUtil::null)
-{
- activate();
-}
-
-BOOL LLVoiceChannelProximal::isActive()
-{
- return callStarted() && LLVoiceClient::getInstance()->inProximalChannel();
-}
-
-void LLVoiceChannelProximal::activate()
-{
- if (callStarted()) return;
-
- LLVoiceChannel::activate();
-
- if (callStarted())
- {
- // this implicitly puts you back in the spatial channel
- LLVoiceClient::getInstance()->leaveNonSpatialChannel();
- }
-}
-
-void LLVoiceChannelProximal::onChange(EStatusType type, const std::string &channelURI, bool proximal)
-{
- if (!proximal)
- {
- return;
- }
-
- if (type < BEGIN_ERROR_STATUS)
- {
- handleStatusChange(type);
- }
- else
- {
- handleError(type);
- }
-}
-
-void LLVoiceChannelProximal::handleStatusChange(EStatusType status)
-{
- // status updates
- switch(status)
- {
- case STATUS_LEFT_CHANNEL:
- // do not notify user when leaving proximal channel
- return;
- case STATUS_VOICE_DISABLED:
- gIMMgr->addSystemMessage(LLUUID::null, "unavailable", mNotifyArgs);
- return;
- default:
- break;
- }
- LLVoiceChannel::handleStatusChange(status);
-}
-
-
-void LLVoiceChannelProximal::handleError(EStatusType status)
-{
- std::string notify;
- switch(status)
- {
- case ERROR_CHANNEL_LOCKED:
- case ERROR_CHANNEL_FULL:
- notify = "ProximalVoiceChannelFull";
- break;
- default:
- break;
- }
-
- // notification
- if (!notify.empty())
- {
- LLNotifications::instance().add(notify, mNotifyArgs);
- }
-
- LLVoiceChannel::handleError(status);
-}
-
-void LLVoiceChannelProximal::deactivate()
-{
- if (callStarted())
- {
- setState(STATE_HUNG_UP);
- }
-}
-
-
-//
-// LLVoiceChannelP2P
-//
-LLVoiceChannelP2P::LLVoiceChannelP2P(const LLUUID& session_id, const std::string& session_name, const LLUUID& other_user_id) :
- LLVoiceChannelGroup(session_id, session_name),
- mOtherUserID(other_user_id),
- mReceivedCall(FALSE)
-{
- // make sure URI reflects encoded version of other user's agent id
- setURI(LLVoiceClient::getInstance()->sipURIFromID(other_user_id));
-}
-
-void LLVoiceChannelP2P::handleStatusChange(EStatusType type)
-{
- // status updates
- switch(type)
- {
- case STATUS_LEFT_CHANNEL:
- if (callStarted() && !mIgnoreNextSessionLeave && !sSuspended)
- {
- if (mState == STATE_RINGING)
- {
- // other user declined call
- LLNotifications::instance().add("P2PCallDeclined", mNotifyArgs);
- }
- else
- {
- // other user hung up
- LLNotifications::instance().add("VoiceChannelDisconnectedP2P", mNotifyArgs);
- }
- deactivate();
- }
- mIgnoreNextSessionLeave = FALSE;
- return;
- default:
- break;
- }
-
- LLVoiceChannel::handleStatusChange(type);
-}
-
-void LLVoiceChannelP2P::handleError(EStatusType type)
-{
- switch(type)
- {
- case ERROR_NOT_AVAILABLE:
- LLNotifications::instance().add("P2PCallNoAnswer", mNotifyArgs);
- break;
- default:
- break;
- }
-
- LLVoiceChannel::handleError(type);
-}
-
-void LLVoiceChannelP2P::activate()
-{
- if (callStarted()) return;
-
- LLVoiceChannel::activate();
-
- if (callStarted())
- {
- // no session handle yet, we're starting the call
- if (mSessionHandle.empty())
- {
- mReceivedCall = FALSE;
- LLVoiceClient::getInstance()->callUser(mOtherUserID);
- }
- // otherwise answering the call
- else
- {
- LLVoiceClient::getInstance()->answerInvite(mSessionHandle);
-
- // using the session handle invalidates it. Clear it out here so we can't reuse it by accident.
- mSessionHandle.clear();
- }
-
- // Add the party to the list of people with which we've recently interacted.
- LLRecentPeople::instance().add(mOtherUserID);
- }
-}
-
-void LLVoiceChannelP2P::getChannelInfo()
-{
- // pretend we have everything we need, since P2P doesn't use channel info
- if (sCurrentVoiceChannel == this)
- {
- setState(STATE_CALL_STARTED);
- }
-}
-
-// receiving session from other user who initiated call
-void LLVoiceChannelP2P::setSessionHandle(const std::string& handle, const std::string &inURI)
-{
- BOOL needs_activate = FALSE;
- if (callStarted())
- {
- // defer to lower agent id when already active
- if (mOtherUserID < gAgent.getID())
- {
- // pretend we haven't started the call yet, so we can connect to this session instead
- deactivate();
- needs_activate = TRUE;
- }
- else
- {
- // we are active and have priority, invite the other user again
- // under the assumption they will join this new session
- mSessionHandle.clear();
- LLVoiceClient::getInstance()->callUser(mOtherUserID);
- return;
- }
- }
-
- mSessionHandle = handle;
-
- // The URI of a p2p session should always be the other end's SIP URI.
- if(!inURI.empty())
- {
- setURI(inURI);
- }
- else
- {
- setURI(LLVoiceClient::getInstance()->sipURIFromID(mOtherUserID));
- }
-
- mReceivedCall = TRUE;
-
- if (needs_activate)
- {
- activate();
- }
-}
-
-void LLVoiceChannelP2P::setState(EState state)
-{
- // HACK: Open/close the call window if needed.
- toggleCallWindowIfNeeded(state);
-
- // you only "answer" voice invites in p2p mode
- // so provide a special purpose message here
- if (mReceivedCall && state == STATE_RINGING)
- {
- gIMMgr->addSystemMessage(mSessionID, "answering", mNotifyArgs);
- mState = state;
- return;
- }
- LLVoiceChannel::setState(state);
-}
-
//
// LLFloaterIMPanel
@@ -1005,13 +181,6 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label,
// enable line history support for instant message bar
mInputEditor->setEnableLineHistory(TRUE);
- if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") )
- {
- LLLogChat::loadHistory(mSessionLabel,
- &chatFromLogFile,
- (void *)this);
- }
-
//*TODO we probably need the same "awaiting message" thing in LLIMFloater
LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(mSessionUUID);
if (!im_session)
@@ -1801,110 +970,8 @@ void LLFloaterIMPanel::removeTypingIndicator(const LLIMInfo* im_info)
}
}
-//static
-void LLFloaterIMPanel::chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata)
-{
- LLFloaterIMPanel* self = (LLFloaterIMPanel*)userdata;
- std::string message = line;
- S32 im_log_option = gSavedPerAccountSettings.getS32("IMLogOptions");
- switch (type)
- {
- case LLLogChat::LOG_EMPTY:
- // add warning log enabled message
- if (im_log_option!=LOG_CHAT)
- {
- message = LLTrans::getString("IM_logging_string");
- }
- break;
- case LLLogChat::LOG_END:
- // add log end message
- if (im_log_option!=LOG_CHAT)
- {
- message = LLTrans::getString("IM_logging_string");
- }
- break;
- case LLLogChat::LOG_LINE:
- // just add normal lines from file
- break;
- default:
- // nothing
- break;
- }
-
- //self->addHistoryLine(line, LLColor4::grey, FALSE);
- self->mHistoryEditor->appendText(message, true, LLStyle::Params().color(LLUIColorTable::instance().getColor("ChatHistoryTextColor")));
- self->mHistoryEditor->blockUndo();
-}
-
-void LLFloaterIMPanel::showSessionStartError(
- const std::string& error_string)
-{
- LLSD args;
- args["REASON"] = LLTrans::getString(error_string);
- args["RECIPIENT"] = getTitle();
-
- LLSD payload;
- payload["session_id"] = mSessionUUID;
-
- LLNotifications::instance().add(
- "ChatterBoxSessionStartError",
- args,
- payload,
- onConfirmForceCloseError);
-}
-
-void LLFloaterIMPanel::showSessionEventError(
- const std::string& event_string,
- const std::string& error_string)
-{
- LLSD args;
- args["REASON"] =
- LLTrans::getString(error_string);
- args["EVENT"] =
- LLTrans::getString(event_string);
- args["RECIPIENT"] = getTitle();
-
- LLNotifications::instance().add(
- "ChatterBoxSessionEventError",
- args);
-}
-
-void LLFloaterIMPanel::showSessionForceClose(
- const std::string& reason_string)
-{
- LLSD args;
-
- args["NAME"] = getTitle();
- args["REASON"] = LLTrans::getString(reason_string);
-
- LLSD payload;
- payload["session_id"] = mSessionUUID;
-
- LLNotifications::instance().add(
- "ForceCloseChatterBoxSession",
- args,
- payload,
- LLFloaterIMPanel::onConfirmForceCloseError);
-
-}
-
//static
void LLFloaterIMPanel::onKickSpeaker(void* user_data)
{
}
-
-bool LLFloaterIMPanel::onConfirmForceCloseError(const LLSD& notification, const LLSD& response)
-{
- //only 1 option really
- LLUUID session_id = notification["payload"]["session_id"];
-
- if ( gIMMgr )
- {
- LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(
- session_id);
-
- if ( floaterp ) floaterp->closeFloater(FALSE);
- }
- return false;
-}
diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h
index 4e306c7fab..b8f99d45c9 100644
--- a/indra/newview/llimpanel.h
+++ b/indra/newview/llimpanel.h
@@ -50,133 +50,6 @@ class LLIMSpeakerMgr;
class LLPanelActiveSpeakers;
class LLPanelChatControlPanel;
-class LLVoiceChannel : public LLVoiceClientStatusObserver
-{
-public:
- typedef enum e_voice_channel_state
- {
- STATE_NO_CHANNEL_INFO,
- STATE_ERROR,
- STATE_HUNG_UP,
- STATE_READY,
- STATE_CALL_STARTED,
- STATE_RINGING,
- STATE_CONNECTED
- } EState;
-
- LLVoiceChannel(const LLUUID& session_id, const std::string& session_name);
- virtual ~LLVoiceChannel();
-
- /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
-
- virtual void handleStatusChange(EStatusType status);
- virtual void handleError(EStatusType status);
- virtual void deactivate();
- virtual void activate();
- virtual void setChannelInfo(
- const std::string& uri,
- const std::string& credentials);
- virtual void getChannelInfo();
- virtual BOOL isActive();
- virtual BOOL callStarted();
- const std::string& getSessionName() const { return mSessionName; }
-
- const LLUUID getSessionID() { return mSessionID; }
- EState getState() { return mState; }
-
- void updateSessionID(const LLUUID& new_session_id);
- const LLSD& getNotifyArgs() { return mNotifyArgs; }
-
- static LLVoiceChannel* getChannelByID(const LLUUID& session_id);
- static LLVoiceChannel* getChannelByURI(std::string uri);
- static LLVoiceChannel* getCurrentVoiceChannel() { return sCurrentVoiceChannel; }
- static void initClass();
-
- static void suspend();
- static void resume();
-
-protected:
- virtual void setState(EState state);
- void toggleCallWindowIfNeeded(EState state);
- void setURI(std::string uri);
-
- std::string mURI;
- std::string mCredentials;
- LLUUID mSessionID;
- EState mState;
- std::string mSessionName;
- LLSD mNotifyArgs;
- BOOL mIgnoreNextSessionLeave;
- LLHandle<LLPanel> mLoginNotificationHandle;
-
- typedef std::map<LLUUID, LLVoiceChannel*> voice_channel_map_t;
- static voice_channel_map_t sVoiceChannelMap;
-
- typedef std::map<std::string, LLVoiceChannel*> voice_channel_map_uri_t;
- static voice_channel_map_uri_t sVoiceChannelURIMap;
-
- static LLVoiceChannel* sCurrentVoiceChannel;
- static LLVoiceChannel* sSuspendedVoiceChannel;
- static BOOL sSuspended;
-};
-
-class LLVoiceChannelGroup : public LLVoiceChannel
-{
-public:
- LLVoiceChannelGroup(const LLUUID& session_id, const std::string& session_name);
-
- /*virtual*/ void handleStatusChange(EStatusType status);
- /*virtual*/ void handleError(EStatusType status);
- /*virtual*/ void activate();
- /*virtual*/ void deactivate();
- /*vritual*/ void setChannelInfo(
- const std::string& uri,
- const std::string& credentials);
- /*virtual*/ void getChannelInfo();
-
-protected:
- virtual void setState(EState state);
-
-private:
- U32 mRetries;
- BOOL mIsRetrying;
-};
-
-class LLVoiceChannelProximal : public LLVoiceChannel, public LLSingleton<LLVoiceChannelProximal>
-{
-public:
- LLVoiceChannelProximal();
-
- /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
- /*virtual*/ void handleStatusChange(EStatusType status);
- /*virtual*/ void handleError(EStatusType status);
- /*virtual*/ BOOL isActive();
- /*virtual*/ void activate();
- /*virtual*/ void deactivate();
-
-};
-
-class LLVoiceChannelP2P : public LLVoiceChannelGroup
-{
-public:
- LLVoiceChannelP2P(const LLUUID& session_id, const std::string& session_name, const LLUUID& other_user_id);
-
- /*virtual*/ void handleStatusChange(EStatusType status);
- /*virtual*/ void handleError(EStatusType status);
- /*virtual*/ void activate();
- /*virtual*/ void getChannelInfo();
-
- void setSessionHandle(const std::string& handle, const std::string &inURI);
-
-protected:
- virtual void setState(EState state);
-
-private:
- std::string mSessionHandle;
- LLUUID mOtherUserID;
- BOOL mReceivedCall;
-};
-
class LLFloaterIMPanel : public LLFloater
{
public:
@@ -254,16 +127,6 @@ public:
// Handle other participant in the session typing.
void processIMTyping(const LLIMInfo* im_info, BOOL typing);
- static void chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata);
-
- //show error statuses to the user
- void showSessionStartError(const std::string& error_string);
- void showSessionEventError(
- const std::string& event_string,
- const std::string& error_string);
- void showSessionForceClose(const std::string& reason);
-
- static bool onConfirmForceCloseError(const LLSD& notification, const LLSD& response);
private:
// Called by UI methods.
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index b631c991ae..49fc9d8055 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -70,6 +70,7 @@
#include "llviewerwindow.h"
#include "llnotify.h"
#include "llviewerregion.h"
+#include "llvoicechannel.h"
#include "lltrans.h"
#include "llrecentpeople.h"
@@ -134,7 +135,6 @@ LLIMModel::LLIMModel()
addNewMsgCallback(toast_callback);
}
-
LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, const std::vector<LLUUID>& ids)
: mSessionID(session_id),
mName(name),
@@ -144,7 +144,10 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string&
mInitialTargetIDs(ids),
mVoiceChannel(NULL),
mSpeakers(NULL),
- mSessionInitialized(false)
+ mSessionInitialized(false),
+ mCallBackEnabled(true),
+ mTextIMPossible(true),
+ mOtherParticipantIsAvatar(true)
{
if (IM_NOTHING_SPECIAL == type || IM_SESSION_P2P_INVITE == type)
{
@@ -168,6 +171,16 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string&
//so we're already initialized
mSessionInitialized = true;
}
+
+ if (IM_NOTHING_SPECIAL == type)
+ {
+ mCallBackEnabled = LLVoiceClient::getInstance()->isSessionCallBackPossible(mSessionID);
+ mTextIMPossible = LLVoiceClient::getInstance()->isSessionTextIMPossible(mSessionID);
+ mOtherParticipantIsAvatar = LLVoiceClient::getInstance()->isParticipantAvatar(mSessionID);
+ }
+
+ if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") )
+ LLLogChat::loadHistory(mName, &chatFromLogFile, (void *)this);
}
LLIMModel::LLIMSession::~LLIMSession()
@@ -209,6 +222,34 @@ void LLIMModel::LLIMSession::sessionInitReplyReceived(const LLUUID& new_session_
}
}
+void LLIMModel::LLIMSession::addMessage(const std::string& from, const LLUUID& from_id, const std::string& utf8_text, const std::string& time)
+{
+ LLSD message;
+ message["from"] = from;
+ message["from_id"] = from_id;
+ message["message"] = utf8_text;
+ message["time"] = time;
+ message["index"] = (LLSD::Integer)mMsgs.size();
+
+ mMsgs.push_front(message);
+}
+
+void LLIMModel::LLIMSession::chatFromLogFile(LLLogChat::ELogLineType type, const LLSD& msg, void* userdata)
+{
+ if (!userdata) return;
+
+ LLIMSession* self = (LLIMSession*) userdata;
+
+ if (type == LLLogChat::LOG_LINE)
+ {
+ self->addMessage("", LLSD(), msg["message"].asString(), "");
+ }
+ else if (type == LLLogChat::LOG_LLSD)
+ {
+ self->addMessage(msg["from"].asString(), msg["from_id"].asUUID(), msg["message"].asString(), msg["time"].asString());
+ }
+}
+
LLIMModel::LLIMSession* LLIMModel::findIMSession(const LLUUID& session_id) const
{
return get_if_there(LLIMModel::instance().sSessionsMap, session_id,
@@ -272,7 +313,8 @@ void LLIMModel::testMessages()
}
-bool LLIMModel::newSession(LLUUID session_id, std::string name, EInstantMessage type, LLUUID other_participant_id, const std::vector<LLUUID>& ids)
+bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type,
+ const LLUUID& other_participant_id, const std::vector<LLUUID>& ids)
{
if (is_in_map(sSessionsMap, session_id))
{
@@ -289,7 +331,7 @@ bool LLIMModel::newSession(LLUUID session_id, std::string name, EInstantMessage
}
-bool LLIMModel::clearSession(LLUUID session_id)
+bool LLIMModel::clearSession(const LLUUID& session_id)
{
if (sSessionsMap.find(session_id) == sSessionsMap.end()) return false;
delete (sSessionsMap[session_id]);
@@ -297,16 +339,13 @@ bool LLIMModel::clearSession(LLUUID session_id)
return true;
}
-//*TODO remake it, instead of returing the list pass it as as parameter (IB)
-std::list<LLSD> LLIMModel::getMessages(LLUUID session_id, int start_index)
+void LLIMModel::getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index)
{
- std::list<LLSD> return_list;
-
LLIMSession* session = findIMSession(session_id);
if (!session)
{
llwarns << "session " << session_id << "does not exist " << llendl;
- return return_list;
+ return;
}
int i = session->mMsgs.size() - start_index;
@@ -317,7 +356,7 @@ std::list<LLSD> LLIMModel::getMessages(LLUUID session_id, int start_index)
{
LLSD msg;
msg = *iter;
- return_list.push_back(*iter);
+ messages.push_back(*iter);
i--;
}
@@ -327,14 +366,9 @@ std::list<LLSD> LLIMModel::getMessages(LLUUID session_id, int start_index)
arg["session_id"] = session_id;
arg["num_unread"] = 0;
mNoUnreadMsgsSignal(arg);
-
- // TODO: in the future is there a more efficient way to return these
- //of course there is - return as parameter (IB)
- return return_list;
-
}
-bool LLIMModel::addToHistory(LLUUID session_id, std::string from, LLUUID from_id, std::string utf8_text) {
+bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text) {
LLIMSession* session = findIMSession(session_id);
@@ -344,47 +378,33 @@ bool LLIMModel::addToHistory(LLUUID session_id, std::string from, LLUUID from_id
return false;
}
- LLSD message;
- message["from"] = from;
- message["from_id"] = from_id;
- message["message"] = utf8_text;
- message["time"] = LLLogChat::timestamp(false); //might want to add date separately
- message["index"] = (LLSD::Integer)session->mMsgs.size();
-
- session->mMsgs.push_front(message);
+ session->addMessage(from, from_id, utf8_text, LLLogChat::timestamp(false)); //might want to add date separately
return true;
-
}
//*TODO rewrite chat history persistence using LLSD serialization (IB)
-bool LLIMModel::logToFile(const LLUUID& session_id, const std::string& from, const std::string& utf8_text)
+bool LLIMModel::logToFile(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text)
{
S32 im_log_option = gSavedPerAccountSettings.getS32("IMLogOptions");
if (im_log_option != LOG_CHAT)
{
- std::string histstr;
- if (gSavedPerAccountSettings.getBOOL("LogTimestamp"))
- histstr = LLLogChat::timestamp(gSavedPerAccountSettings.getBOOL("LogTimestampDate")) + from + IM_SEPARATOR + utf8_text;
- else
- histstr = from + IM_SEPARATOR + utf8_text;
-
if(im_log_option == LOG_BOTH_TOGETHER)
{
- LLLogChat::saveHistory(std::string("chat"), histstr);
+ LLLogChat::saveHistory(std::string("chat"), from, from_id, utf8_text);
return true;
}
else
{
- LLLogChat::saveHistory(LLIMModel::getInstance()->getName(session_id), histstr);
+ LLLogChat::saveHistory(LLIMModel::getInstance()->getName(session_id), from, from_id, utf8_text);
return true;
}
}
return false;
}
-//*TODO add const qualifier and pass by references (IB)
-bool LLIMModel::addMessage(LLUUID session_id, std::string from, LLUUID from_id, std::string utf8_text, bool log2file /* = true */) {
+bool LLIMModel::addMessage(const LLUUID& session_id, const std::string& from, const LLUUID& from_id,
+ const std::string& utf8_text, bool log2file /* = true */) {
LLIMSession* session = findIMSession(session_id);
if (!session)
@@ -394,7 +414,7 @@ bool LLIMModel::addMessage(LLUUID session_id, std::string from, LLUUID from_id,
}
addToHistory(session_id, from, from_id, utf8_text);
- if (log2file) logToFile(session_id, from, utf8_text);
+ if (log2file) logToFile(session_id, from, from_id, utf8_text);
session->mNumUnread++;
@@ -506,7 +526,7 @@ void LLIMModel::sendTypingState(LLUUID session_id, LLUUID other_participant_id,
gAgent.sendReliableMessage();
}
-void LLIMModel::sendLeaveSession(LLUUID session_id, LLUUID other_participant_id)
+void LLIMModel::sendLeaveSession(const LLUUID& session_id, const LLUUID& other_participant_id)
{
if(session_id.notNull())
{
@@ -890,20 +910,11 @@ public:
{
gIMMgr->clearPendingAgentListUpdates(mSessionID);
gIMMgr->clearPendingInvitation(mSessionID);
-
- LLFloaterIMPanel* floaterp =
- gIMMgr->findFloaterBySession(mSessionID);
-
- if ( floaterp )
+ if ( 404 == statusNum )
{
- if ( 404 == statusNum )
- {
- std::string error_string;
- error_string = "does not exist";
-
- floaterp->showSessionStartError(
- error_string);
- }
+ std::string error_string;
+ error_string = "does not exist";
+ gIMMgr->showSessionStartError(error_string, mSessionID);
}
}
}
@@ -955,6 +966,106 @@ LLUUID LLIMMgr::computeSessionID(
return session_id;
}
+inline LLFloater* getFloaterBySessionID(const LLUUID session_id)
+{
+ LLFloater* floater = NULL;
+ if ( gIMMgr )
+ {
+ floater = dynamic_cast < LLFloater* >
+ ( gIMMgr->findFloaterBySession(session_id) );
+ }
+ if ( !floater )
+ {
+ floater = dynamic_cast < LLFloater* >
+ ( LLIMFloater::findInstance(session_id) );
+ }
+ return floater;
+}
+
+void
+LLIMMgr::showSessionStartError(
+ const std::string& error_string,
+ const LLUUID session_id)
+{
+ const LLFloater* floater = getFloaterBySessionID (session_id);
+ if (!floater) return;
+
+ LLSD args;
+ args["REASON"] = LLTrans::getString(error_string);
+ args["RECIPIENT"] = floater->getTitle();
+
+ LLSD payload;
+ payload["session_id"] = session_id;
+
+ LLNotifications::instance().add(
+ "ChatterBoxSessionStartError",
+ args,
+ payload,
+ LLIMMgr::onConfirmForceCloseError);
+}
+
+void
+LLIMMgr::showSessionEventError(
+ const std::string& event_string,
+ const std::string& error_string,
+ const LLUUID session_id)
+{
+ const LLFloater* floater = getFloaterBySessionID (session_id);
+ if (!floater) return;
+
+ LLSD args;
+ args["REASON"] =
+ LLTrans::getString(error_string);
+ args["EVENT"] =
+ LLTrans::getString(event_string);
+ args["RECIPIENT"] = floater->getTitle();
+
+ LLNotifications::instance().add(
+ "ChatterBoxSessionEventError",
+ args);
+}
+
+void
+LLIMMgr::showSessionForceClose(
+ const std::string& reason_string,
+ const LLUUID session_id)
+{
+ const LLFloater* floater = getFloaterBySessionID (session_id);
+ if (!floater) return;
+
+ LLSD args;
+
+ args["NAME"] = floater->getTitle();
+ args["REASON"] = LLTrans::getString(reason_string);
+
+ LLSD payload;
+ payload["session_id"] = session_id;
+
+ LLNotifications::instance().add(
+ "ForceCloseChatterBoxSession",
+ args,
+ payload,
+ LLIMMgr::onConfirmForceCloseError);
+}
+
+//static
+bool
+LLIMMgr::onConfirmForceCloseError(
+ const LLSD& notification,
+ const LLSD& response)
+{
+ //only 1 option really
+ LLUUID session_id = notification["payload"]["session_id"];
+
+ LLFloater* floater = getFloaterBySessionID (session_id);
+ if ( floater )
+ {
+ floater->closeFloater(FALSE);
+ }
+ return false;
+}
+
+
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLIncomingCallDialog
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1114,29 +1225,6 @@ void LLIncomingCallDialog::processCallResponse(S32 response)
}
}
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLIMViewFriendObserver
-//
-// Bridge to suport knowing when the inventory has changed.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-class LLIMViewFriendObserver : public LLFriendObserver
-{
-public:
- LLIMViewFriendObserver(LLIMMgr* tv) : mTV(tv) {}
- virtual ~LLIMViewFriendObserver() {}
- virtual void changed(U32 mask)
- {
- if(mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::ONLINE))
- {
- mTV->refresh();
- }
- }
-protected:
- LLIMMgr* mTV;
-};
-
-
bool inviteUserResponse(const LLSD& notification, const LLSD& response)
{
const LLSD& payload = notification["payload"];
@@ -1237,7 +1325,6 @@ bool inviteUserResponse(const LLSD& notification, const LLSD& response)
//
LLIMMgr::LLIMMgr() :
- mFriendObserver(NULL),
mIMReceived(FALSE)
{
static bool registered_dialog = false;
@@ -1246,21 +1333,11 @@ LLIMMgr::LLIMMgr() :
LLFloaterReg::add("incoming_call", "floater_incoming_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIncomingCallDialog>);
registered_dialog = true;
}
-
- mFriendObserver = new LLIMViewFriendObserver(this);
- LLAvatarTracker::instance().addObserver(mFriendObserver);
mPendingInvitations = LLSD::emptyMap();
mPendingAgentListUpdates = LLSD::emptyMap();
}
-LLIMMgr::~LLIMMgr()
-{
- LLAvatarTracker::instance().removeObserver(mFriendObserver);
- delete mFriendObserver;
- // Children all cleaned up by default view destructor.
-}
-
// Add a message to a session.
void LLIMMgr::addMessage(
const LLUUID& session_id,
@@ -1299,9 +1376,10 @@ void LLIMMgr::addMessage(
fixed_session_name = session_name;
}
- if (!LLIMModel::getInstance()->findIMSession(new_session_id))
+ bool new_session = !hasSession(new_session_id);
+ if (new_session)
{
- LLIMModel::getInstance()->newSession(session_id, fixed_session_name, dialog, other_participant_id);
+ LLIMModel::getInstance()->newSession(new_session_id, fixed_session_name, dialog, other_participant_id);
}
floater = findFloaterBySession(new_session_id);
@@ -1318,15 +1396,16 @@ void LLIMMgr::addMessage(
// create IM window as necessary
if(!floater)
{
-
-
floater = createFloater(
new_session_id,
other_participant_id,
fixed_session_name,
dialog,
FALSE);
+ }
+ if (new_session)
+ {
// When we get a new IM, and if you are a god, display a bit
// of information about the source. This is to help liaisons
// when answering questions.
@@ -1336,7 +1415,7 @@ void LLIMMgr::addMessage(
std::ostringstream bonus_info;
bonus_info << LLTrans::getString("***")+ " "+ LLTrans::getString("IMParentEstate") + ":" + " "
<< parent_estate_id
- << ((parent_estate_id == 1) ? "," + LLTrans::getString("IMMainland") : "")
+ << ((parent_estate_id == 1) ? "," + LLTrans::getString("IMMainland") : "")
<< ((parent_estate_id == 5) ? "," + LLTrans::getString ("IMTeen") : "");
// once we have web-services (or something) which returns
@@ -1439,10 +1518,7 @@ S32 LLIMMgr::getNumberOfUnreadIM()
S32 num = 0;
for(it = LLIMModel::sSessionsMap.begin(); it != LLIMModel::sSessionsMap.end(); ++it)
{
- if((*it).first != mBeingRemovedSessionID)
- {
- num += (*it).second->mNumUnread;
- }
+ num += (*it).second->mNumUnread;
}
return num;
@@ -1458,15 +1534,6 @@ BOOL LLIMMgr::getIMReceived() const
return mIMReceived;
}
-// This method returns TRUE if the local viewer has a session
-// currently open keyed to the uuid.
-BOOL LLIMMgr::isIMSessionOpen(const LLUUID& uuid)
-{
- LLFloaterIMPanel* floater = findFloaterBySession(uuid);
- if(floater) return TRUE;
- return FALSE;
-}
-
LLUUID LLIMMgr::addP2PSession(const std::string& name,
const LLUUID& other_participant_id,
const std::string& voice_session_handle,
@@ -1560,41 +1627,25 @@ bool LLIMMgr::leaveSession(const LLUUID& session_id)
return true;
}
-// This removes the panel referenced by the uuid, and then restores
-// internal consistency. The internal pointer is not deleted? Did you mean
-// a pointer to the corresponding LLIMSession? Session data is cleared now.
-// Put a copy of UUID to avoid problem when passed reference becames invalid
-// if it has been come from the object removed in observer.
-void LLIMMgr::removeSession(LLUUID session_id)
+// Removes data associated with a particular session specified by session_id
+void LLIMMgr::removeSession(const LLUUID& session_id)
{
- if (mBeingRemovedSessionID == session_id)
- {
- return;
- }
+ llassert_always(hasSession(session_id));
+ //*TODO remove this floater thing when Communicate Floater is being deleted (IB)
LLFloaterIMPanel* floater = findFloaterBySession(session_id);
if(floater)
{
mFloaters.erase(floater->getHandle());
LLFloaterChatterBox::getInstance()->removeFloater(floater);
- //mTabContainer->removeTabPanel(floater);
-
- clearPendingInvitation(session_id);
- clearPendingAgentListUpdates(session_id);
}
- // for some purposes storing ID of a sessios that is being removed
- mBeingRemovedSessionID = session_id;
- notifyObserverSessionRemoved(session_id);
+ clearPendingInvitation(session_id);
+ clearPendingAgentListUpdates(session_id);
- //if we don't clear session data on removing the session
- //we can't use LLBottomTray as observer of session creation/delettion and
- //creating chiclets only on session created even, we need to handle chiclets creation
- //the same way as LLFloaterIMPanels were managed.
LLIMModel::getInstance()->clearSession(session_id);
- // now this session is completely removed
- mBeingRemovedSessionID.setNull();
+ notifyObserverSessionRemoved(session_id);
}
void LLIMMgr::inviteToSession(
@@ -1723,10 +1774,6 @@ void LLIMMgr::onInviteNameLookup(LLSD payload, const LLUUID& id, const std::stri
}
}
-void LLIMMgr::refresh()
-{
-}
-
void LLIMMgr::disconnectAllSessions()
{
LLFloaterIMPanel* floater = NULL;
@@ -2038,6 +2085,12 @@ void LLIMMgr::processIMTypingCore(const LLIMInfo* im_info, BOOL typing)
{
floater->processIMTyping(im_info, typing);
}
+
+ LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
+ if ( im_floater )
+ {
+ im_floater->processIMTyping(im_info, typing);
+ }
}
class LLViewerChatterBoxSessionStartReply : public LLHTTPNode
@@ -2087,19 +2140,21 @@ public:
}
}
+ LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
+ if ( im_floater )
+ {
+ if ( body.has("session_info") )
+ {
+ im_floater->processSessionUpdate(body["session_info"]);
+ }
+ }
+
gIMMgr->clearPendingAgentListUpdates(session_id);
}
else
{
- //throw an error dialog and close the temp session's
- //floater
- LLFloaterIMPanel* floater =
- gIMMgr->findFloaterBySession(temp_session_id);
-
- if ( floater )
- {
- floater->showSessionStartError(body["error"].asString());
- }
+ //throw an error dialog and close the temp session's floater
+ gIMMgr->showSessionStartError(body["error"].asString(), temp_session_id);
}
gIMMgr->clearPendingAgentListUpdates(session_id);
@@ -2132,15 +2187,10 @@ public:
if ( !success )
{
//throw an error dialog
- LLFloaterIMPanel* floater =
- gIMMgr->findFloaterBySession(session_id);
-
- if (floater)
- {
- floater->showSessionEventError(
- body["event"].asString(),
- body["error"].asString());
- }
+ gIMMgr->showSessionEventError(
+ body["event"].asString(),
+ body["error"].asString(),
+ session_id);
}
}
};
@@ -2158,13 +2208,7 @@ public:
session_id = input["body"]["session_id"].asUUID();
reason = input["body"]["reason"].asString();
- LLFloaterIMPanel* floater =
- gIMMgr ->findFloaterBySession(session_id);
-
- if ( floater )
- {
- floater->showSessionForceClose(reason);
- }
+ gIMMgr->showSessionForceClose(reason, session_id);
}
};
@@ -2202,11 +2246,17 @@ public:
const LLSD& context,
const LLSD& input) const
{
- LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(input["body"]["session_id"].asUUID());
+ LLUUID session_id = input["body"]["session_id"].asUUID();
+ LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(session_id);
if (floaterp)
{
floaterp->processSessionUpdate(input["body"]["info"]);
}
+ LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
+ if ( im_floater )
+ {
+ im_floater->processSessionUpdate(input["body"]["info"]);
+ }
}
};
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index 68beb29034..d0bd594df1 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -34,12 +34,13 @@
#define LL_LLIMVIEW_H
#include "lldarray.h"
-#include "llfloateractivespeakers.h" //for LLIMSpeakerMgr
+#include "llspeakers.h" //for LLIMSpeakerMgr
#include "llimpanel.h" //for voice channels
#include "llmodaldialog.h"
#include "llinstantmessage.h"
#include "lluuid.h"
#include "llmultifloater.h"
+#include "lllogchat.h"
class LLFloaterChatterBox;
class LLUUID;
@@ -57,6 +58,8 @@ public:
virtual ~LLIMSession();
void sessionInitReplyReceived(const LLUUID& new_session_id);
+ void addMessage(const std::string& from, const LLUUID& from_id, const std::string& utf8_text, const std::string& time);
+ static void chatFromLogFile(LLLogChat::ELogLineType type, const LLSD& msg, void* userdata);
LLUUID mSessionID;
std::string mName;
@@ -70,6 +73,13 @@ public:
LLIMSpeakerMgr* mSpeakers;
bool mSessionInitialized;
+
+ //true if calling back the session URI after the session has closed is possible.
+ //Currently this will be false only for PSTN P2P calls.
+ bool mCallBackEnabled;
+
+ bool mTextIMPossible;
+ bool mOtherParticipantIsAvatar;
};
@@ -104,18 +114,35 @@ public:
boost::signals2::connection addNewMsgCallback( session_callback_t cb ) { return mNewMsgSignal.connect(cb); }
boost::signals2::connection addNoUnreadMsgsCallback( session_callback_t cb ) { return mNoUnreadMsgsSignal.connect(cb); }
- bool newSession(LLUUID session_id, std::string name, EInstantMessage type, LLUUID other_participant_id,
+ /**
+ * Create new session object in a model
+ */
+ bool newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id,
const std::vector<LLUUID>& ids = std::vector<LLUUID>());
- bool clearSession(LLUUID session_id);
- std::list<LLSD> getMessages(LLUUID session_id, int start_index = 0);
- bool addMessage(LLUUID session_id, std::string from, LLUUID other_participant_id, std::string utf8_text, bool log2file = true);
- bool addToHistory(LLUUID session_id, std::string from, LLUUID from_id, std::string utf8_text);
+ /**
+ * Remove all session data associated with a session specified by session_id
+ */
+ bool clearSession(const LLUUID& session_id);
- bool logToFile(const LLUUID& session_id, const std::string& from, const std::string& utf8_text);
+ /**
+ * Populate supplied std::list with messages starting from index specified by start_index
+ */
+ void getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index = 0);
- //used to get the name of the session, for use as the title
- //currently just the other avatar name
+ /**
+ * Add a message to an IM Model - the message is saved in a message store associated with a session specified by session_id
+ * and also saved into a file if log2file is specified.
+ * It sends new message signal for each added message.
+ */
+ bool addMessage(const LLUUID& session_id, const std::string& from, const LLUUID& other_participant_id, const std::string& utf8_text, bool log2file = true);
+
+ /**
+ * Get a session's name.
+ * For a P2P chat - it's an avatar's name,
+ * For a group chat - it's a group's name
+ * For an ad-hoc chat - is received from the server and is in a from of "<Avatar's name> conference"
+ */
const std::string& getName(const LLUUID& session_id) const;
/**
@@ -150,7 +177,7 @@ public:
*/
LLIMSpeakerMgr* getSpeakerManager(const LLUUID& session_id) const;
- static void sendLeaveSession(LLUUID session_id, LLUUID other_participant_id);
+ static void sendLeaveSession(const LLUUID& session_id, const LLUUID& other_participant_id);
static bool sendStartSession(const LLUUID& temp_session_id, const LLUUID& other_participant_id,
const std::vector<LLUUID>& ids, EInstantMessage dialog);
static void sendTypingState(LLUUID session_id, LLUUID other_participant_id, BOOL typing);
@@ -158,6 +185,18 @@ public:
const LLUUID& other_participant_id, EInstantMessage dialog);
void testMessages();
+
+private:
+
+ /**
+ * Add message to a list of message associated with session specified by session_id
+ */
+ bool addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text);
+
+ /**
+ * Save an IM message into a file
+ */
+ bool logToFile(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text);
};
class LLIMSessionObserver
@@ -183,7 +222,7 @@ public:
};
LLIMMgr();
- virtual ~LLIMMgr();
+ virtual ~LLIMMgr() {};
// Add a message to a session. The session can keyed to sesion id
// or agent id.
@@ -200,11 +239,6 @@ public:
void addSystemMessage(const LLUUID& session_id, const std::string& message_name, const LLSD& args);
- // This method returns TRUE if the local viewer has a session
- // currently open keyed to the uuid. The uuid can be keyed by
- // either session id or agent id.
- BOOL isIMSessionOpen(const LLUUID& uuid);
-
// This adds a session to the talk view. The name is the local
// name of the session, dialog specifies the type of
// session. Since sessions can be keyed off of first recipient or
@@ -250,9 +284,6 @@ public:
void processIMTypingStart(const LLIMInfo* im_info);
void processIMTypingStop(const LLIMInfo* im_info);
- // Rebuild stuff
- void refresh();
-
void notifyNewIM();
void clearNewIMNotification();
@@ -268,10 +299,6 @@ public:
// good connection.
void disconnectAllSessions();
- // This is a helper function to determine what kind of im session
- // should be used for the given agent.
- static EInstantMessage defaultIMTypeForAgent(const LLUUID& agent_id);
-
BOOL hasSession(const LLUUID& session_id);
// This method returns the im panel corresponding to the uuid
@@ -290,11 +317,18 @@ public:
void clearPendingAgentListUpdates(const LLUUID& session_id);
//HACK: need a better way of enumerating existing session, or listening to session create/destroy events
+ //@deprecated, is used only by LLToolBox, which is not used anywhere, right? (IB)
const std::set<LLHandle<LLFloater> >& getIMFloaterHandles() { return mFloaters; }
void addSessionObserver(LLIMSessionObserver *);
void removeSessionObserver(LLIMSessionObserver *);
+ //show error statuses to the user
+ void showSessionStartError(const std::string& error_string, const LLUUID session_id);
+ void showSessionEventError(const std::string& event_string, const std::string& error_string, const LLUUID session_id);
+ void showSessionForceClose(const std::string& reason, const LLUUID session_id);
+ static bool onConfirmForceCloseError(const LLSD& notification, const LLSD& response);
+
/**
* Start call in a session
* @return false if voice channel doesn't exist
@@ -308,10 +342,11 @@ public:
bool endCall(const LLUUID& session_id);
private:
- // This removes the panel referenced by the uuid, and then
- // restores internal consistency. The internal pointer is not
- // deleted.
- void removeSession(LLUUID session_id);
+
+ /**
+ * Remove data associated with a particular session specified by session_id
+ */
+ void removeSession(const LLUUID& session_id);
// create a panel and update internal representation for
// consistency. Returns the pointer, caller (the class instance
@@ -340,8 +375,9 @@ private:
void notifyObserverSessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id);
private:
+
+ //*TODO should be deleted when Communicate Floater is being deleted
std::set<LLHandle<LLFloater> > mFloaters;
- LLFriendObserver* mFriendObserver;
typedef std::list <LLIMSessionObserver *> session_observers_list_t;
session_observers_list_t mSessionObservers;
@@ -351,9 +387,6 @@ private:
LLSD mPendingInvitations;
LLSD mPendingAgentListUpdates;
- // ID of a session that is being removed: observers are already told
- // that this session is being removed, but it is still present in the sessions' map
- LLUUID mBeingRemovedSessionID;
};
class LLIncomingCallDialog : public LLModalDialog
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 3aa35d98f8..59f70ea1bd 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1,11 +1,11 @@
-/**
+/**
* @file llinventorybridge.cpp
* @brief Implementation of the Inventory-Folder-View-Bridge classes.
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
- *
+ *
* Copyright (c) 2001-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
@@ -13,17 +13,17 @@
* ("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.
@@ -83,7 +83,7 @@
#include "llvoavatar.h"
#include "llwearable.h"
#include "llwearablelist.h"
-#include "llviewermessage.h"
+#include "llviewermessage.h"
#include "llviewerregion.h"
#include "llvoavatarself.h"
#include "lltabcontainer.h"
@@ -147,8 +147,8 @@ std::string ICON_NAME[ICON_NAME_COUNT] =
"Inv_Undershirt",
"Inv_Underpants",
"Inv_Skirt",
- "inv_item_alpha.tga",
- "inv_item_tattoo.tga",
+ "Inv_Alpha",
+ "Inv_Tattoo",
"Inv_Animation",
"Inv_Gesture",
@@ -237,7 +237,7 @@ void LLInvFVBridge::renameLinkedItems(const LLUUID &item_id, const std::string&
{
return;
}
-
+
LLInventoryModel::item_array_t item_array = model->collectLinkedItems(item_id);
for (LLInventoryModel::item_array_t::iterator iter = item_array.begin();
iter != item_array.end();
@@ -245,7 +245,7 @@ void LLInvFVBridge::renameLinkedItems(const LLUUID &item_id, const std::string&
{
LLViewerInventoryItem *linked_item = (*iter);
if (linked_item->getUUID() == item_id) continue;
-
+
LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(linked_item);
new_item->rename(new_name);
new_item->updateServer(FALSE);
@@ -290,7 +290,7 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc
S32 count = batch.count();
S32 i,j;
for(i = 0; i < count; ++i)
- {
+ {
bridge = (LLInvFVBridge*)(batch.get(i));
if(!bridge || !bridge->isItemRemovable()) continue;
item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID());
@@ -303,7 +303,7 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc
}
}
for(i = 0; i < count; ++i)
- {
+ {
bridge = (LLInvFVBridge*)(batch.get(i));
if(!bridge || !bridge->isItemRemovable()) continue;
cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID());
@@ -506,7 +506,7 @@ BOOL LLInvFVBridge::isClipboardPasteableAsLink() const
return TRUE;
}
-void hideContextEntries(LLMenuGL& menu,
+void hideContextEntries(LLMenuGL& menu,
const std::vector<std::string> &entries_to_show,
const std::vector<std::string> &disabled_entries)
{
@@ -523,8 +523,8 @@ void hideContextEntries(LLMenuGL& menu,
{
hideContextEntries(*branchp->getBranch(), entries_to_show, disabled_entries);
}
-
-
+
+
bool found = false;
std::vector<std::string>::const_iterator itor2;
for (itor2 = entries_to_show.begin(); itor2 != entries_to_show.end(); ++itor2)
@@ -552,8 +552,8 @@ void hideContextEntries(LLMenuGL& menu,
}
// Helper for commonly-used entries
-void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
- std::vector<std::string> &items,
+void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
+ std::vector<std::string> &items,
std::vector<std::string> &disabled_items, U32 flags)
{
items.push_back(std::string("Rename"));
@@ -565,7 +565,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
if (show_asset_id)
{
items.push_back(std::string("Copy Asset UUID"));
- if ( (! ( isItemPermissive() || gAgent.isGodlike() ) )
+ if ( (! ( isItemPermissive() || gAgent.isGodlike() ) )
|| (flags & FIRST_SELECTED_ITEM) == 0)
{
disabled_items.push_back(std::string("Copy Asset UUID"));
@@ -638,7 +638,7 @@ BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
{
return FALSE;
}
-
+
*id = obj->getUUID();
//object_ids.put(obj->getUUID());
@@ -808,7 +808,7 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
}
new_listener = new LLLandmarkBridge(inventory, uuid, flags);
break;
-
+
case LLAssetType::AT_CALLINGCARD:
if(!(inv_type == LLInventoryType::IT_CALLINGCARD))
{
@@ -1100,7 +1100,7 @@ PermissionMask LLItemBridge::getPermissionMask() const
{
LLViewerInventoryItem* item = getItem();
PermissionMask perm_mask = 0;
- if(item)
+ if(item)
{
BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID());
BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID());
@@ -1126,9 +1126,9 @@ const std::string& LLItemBridge::getDisplayName() const
void LLItemBridge::buildDisplayName(LLInventoryItem* item, std::string& name)
{
- if(item)
+ if(item)
{
- name.assign(item->getName());
+ name.assign(item->getName());
}
else
{
@@ -1137,9 +1137,9 @@ void LLItemBridge::buildDisplayName(LLInventoryItem* item, std::string& name)
}
LLFontGL::StyleFlags LLItemBridge::getLabelStyle() const
-{
+{
U8 font = LLFontGL::NORMAL;
-
+
if( gAgentWearables.isWearingItem( mUUID ) )
{
// llinfos << "BOLD" << llendl;
@@ -1165,7 +1165,7 @@ std::string LLItemBridge::getLabelSuffix() const
static std::string BROKEN_LINK = LLTrans::getString("broken_link");
std::string suffix;
LLInventoryItem* item = getItem();
- if(item)
+ if(item)
{
// it's a bit confusing to put nocopy/nomod/etc on calling cards.
if(LLAssetType::AT_CALLINGCARD != item->getType()
@@ -1294,9 +1294,9 @@ BOOL LLItemBridge::isItemCopyable() const
{
return FALSE;
}
-
+
// All items can be copied, not all can be pasted.
- // The only time an item can't be copied is if it's a link
+ // The only time an item can't be copied is if it's a link
// return (item->getPermissions().allowCopyBy(gAgent.getID()));
if (item->getIsLinkType())
{
@@ -1348,7 +1348,7 @@ BOOL LLItemBridge::isItemPermissive() const
LLFolderBridge* LLFolderBridge::sSelf=NULL;
// Can be moved to another folder
-BOOL LLFolderBridge::isItemMovable() const
+BOOL LLFolderBridge::isItemMovable() const
{
LLInventoryObject* obj = getInventoryObject();
if(obj)
@@ -1367,7 +1367,7 @@ void LLFolderBridge::selectItem()
BOOL LLFolderBridge::isItemRemovable()
{
LLInventoryModel* model = getInventoryModel();
- if(!model)
+ if(!model)
{
return FALSE;
}
@@ -1478,7 +1478,7 @@ BOOL LLFolderBridge::isClipboardPasteable() const
LLInventoryClipboard::instance().retrieve(objects);
const LLViewerInventoryCategory *current_cat = getCategory();
- // Search for the direct descendent of current Friends subfolder among all pasted items,
+ // Search for the direct descendent of current Friends subfolder among all pasted items,
// and return false if is found.
for(S32 i = objects.count() - 1; i >= 0; --i)
{
@@ -1500,7 +1500,7 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const
{
return FALSE;
}
-
+
const LLInventoryModel* model = getInventoryModel();
if (!model)
{
@@ -1523,7 +1523,7 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const
{
const LLUUID &cat_id = cat->getUUID();
// Don't allow recursive pasting
- if ((cat_id == current_cat_id) ||
+ if ((cat_id == current_cat_id) ||
model->isObjectDescendentOf(current_cat_id, cat_id))
{
return FALSE;
@@ -1549,7 +1549,7 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const
BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
BOOL drop)
{
- // This should never happen, but if an inventory item is incorrectly parented,
+ // This should never happen, but if an inventory item is incorrectly parented,
// the UI will get confused and pass in a NULL.
if(!inv_cat) return FALSE;
@@ -1611,7 +1611,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
break;
}
}
-
+
if( is_movable )
{
if( move_is_into_trash )
@@ -1642,7 +1642,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
}
}
-
+
accept = is_movable
&& (mUUID != cat_id) // Can't move a folder into itself
&& (mUUID != inv_cat->getParentUUID()) // Avoid moves that would change nothing
@@ -1663,7 +1663,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
}
}
// if target is an outfit or current outfit folder we use link
- if (move_is_into_current_outfit || move_is_into_outfit)
+ if (move_is_into_current_outfit || move_is_into_outfit)
{
#if SUPPORT_ENSEMBLES
// BAP - should skip if dup.
@@ -1686,7 +1686,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
}
else
{
-
+
// Reparent the folder and restamp children if it's moving
// into trash.
LLInvFVBridge::changeCategoryParent(
@@ -1723,7 +1723,7 @@ void warn_move_inventory(LLViewerObject* object, LLMoveInv* move_inv)
// Move/copy all inventory items from the Contents folder of an in-world
// object to the agent's inventory, inside a given category.
-BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
+BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
const LLUUID& category_id,
BOOL drop,
void (*callback)(S32, void*),
@@ -1750,7 +1750,7 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
llinfos << "Object contents not found for drop." << llendl;
return FALSE;
}
-
+
BOOL accept = TRUE;
BOOL is_move = FALSE;
@@ -1836,7 +1836,7 @@ bool LLFindCOFValidItems::operator()(LLInventoryCategory* cat,
{
LLViewerInventoryCategory *linked_category = ((LLViewerInventoryItem*)item)->getLinkedCategory(); // BAP - safe?
// BAP remove AT_NONE support after ensembles are fully working?
- return (linked_category &&
+ return (linked_category &&
((linked_category->getPreferredType() == LLAssetType::AT_NONE) ||
(LLAssetType::lookupIsEnsembleCategoryType(linked_category->getPreferredType()))));
}
@@ -1878,7 +1878,7 @@ public:
gInventory.removeObserver(this);
delete this;
}
-
+
protected:
LLUUID mCatID;
@@ -1973,7 +1973,7 @@ void LLRightClickInventoryFetchDescendentsObserver::done()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLInventoryWearObserver
//
-// Observer for "copy and wear" operation to support knowing
+// Observer for "copy and wear" operation to support knowing
// when the all of the contents have been added to inventory.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LLInventoryCopyAndWearObserver : public LLInventoryObserver
@@ -1995,7 +1995,7 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask)
{
if((mask & (LLInventoryObserver::ADD)) != 0)
{
- if (!mFolderAdded)
+ if (!mFolderAdded)
{
const std::set<LLUUID>& changed_items = gInventory.getChangedIDs();
@@ -2003,7 +2003,7 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask)
std::set<LLUUID>::const_iterator id_end = changed_items.end();
for (;id_it != id_end; ++id_it)
{
- if ((*id_it) == mCatID)
+ if ((*id_it) == mCatID)
{
mFolderAdded = TRUE;
break;
@@ -2011,7 +2011,7 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask)
}
}
- if (mFolderAdded)
+ if (mFolderAdded)
{
LLViewerInventoryCategory* category = gInventory.getCategory(mCatID);
@@ -2029,7 +2029,7 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask)
LLAppearanceManager::wearInventoryCategory(category, FALSE, TRUE);
delete this;
}
- }
+ }
}
}
@@ -2091,12 +2091,12 @@ void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model
if(!model) return;
LLViewerInventoryCategory* cat = getCategory();
if(!cat) return;
-
+
remove_inventory_category_from_avatar ( cat );
return;
- }
+ }
else if ("purge" == action)
- {
+ {
purgeItem(model, mUUID);
return;
}
@@ -2270,7 +2270,7 @@ void LLFolderBridge::pasteFromClipboard()
{
if(LLInventoryClipboard::instance().isCutMode())
{
- // move_inventory_item() is not enough,
+ // move_inventory_item() is not enough,
//we have to update inventory locally too
changeItemParent(model, dynamic_cast<LLViewerInventoryItem*>(item), parent_id, FALSE);
}
@@ -2347,7 +2347,7 @@ void LLFolderBridge::folderOptionsMenu()
// BAP change once we're no longer treating regular categories as ensembles.
const bool is_ensemble = category && (type == LLAssetType::AT_NONE ||
LLAssetType::lookupIsEnsembleCategoryType(type));
-
+
// calling card related functionality for folders.
// Only enable calling-card related options for non-default folders.
@@ -2361,7 +2361,7 @@ void LLFolderBridge::folderOptionsMenu()
mItems.push_back(std::string("IM All Contacts In Folder"));
}
}
-
+
// wearables related functionality for folders.
//is_wearable
LLFindWearables is_wearable;
@@ -2416,7 +2416,7 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND);
mItems.clear(); //adding code to clear out member Items (which means Items should not have other data here at this point)
- mDisabledItems.clear(); //adding code to clear out disabled members from previous
+ mDisabledItems.clear(); //adding code to clear out disabled members from previous
if (lost_and_found_id == mUUID)
{
// This is the lost+found folder.
@@ -2458,13 +2458,13 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
mItems.push_back(std::string("New Clothes"));
mItems.push_back(std::string("New Body Parts"));
mItems.push_back(std::string("Change Type"));
-
+
LLViewerInventoryCategory *cat = getCategory();
if (cat && LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType()))
{
mDisabledItems.push_back(std::string("Change Type"));
}
-
+
getClipboardEntries(false, mItems, mDisabledItems, flags);
}
else
@@ -2479,24 +2479,24 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
//Added by spatters to force inventory pull on right-click to display folder options correctly. 07-17-06
mCallingCards = mWearables = FALSE;
-
+
LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);
if (checkFolderForContentsOfType(model, is_callingcard))
{
mCallingCards=TRUE;
}
-
+
LLFindWearables is_wearable;
LLIsType is_object( LLAssetType::AT_OBJECT );
LLIsType is_gesture( LLAssetType::AT_GESTURE );
-
+
if (checkFolderForContentsOfType(model, is_wearable) ||
checkFolderForContentsOfType(model, is_object) ||
checkFolderForContentsOfType(model, is_gesture) )
{
mWearables=TRUE;
}
-
+
mMenu = &menu;
sSelf = this;
LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(FALSE);
@@ -2709,7 +2709,7 @@ void LLFolderBridge::modifyOutfit(BOOL append)
if(!model) return;
LLViewerInventoryCategory* cat = getCategory();
if(!cat) return;
-
+
// BAP - was:
// wear_inventory_category_on_avatar( cat, append );
LLAppearanceManager::wearInventoryCategory( cat, FALSE, append );
@@ -2735,8 +2735,8 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response
}
two_uuids_list_t::iterator move_it;
- for (move_it = move_inv->mMoveList.begin();
- move_it != move_inv->mMoveList.end();
+ for (move_it = move_inv->mMoveList.begin();
+ move_it != move_inv->mMoveList.end();
++move_it)
{
object->moveInventory(move_it->first, move_it->second);
@@ -2845,7 +2845,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
LLUUID current_outfit_id = model->findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT);
BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLAssetType::AT_OUTFIT);
-
+
if(is_movable && move_is_into_trash)
{
switch(inv_item->getType())
@@ -2873,7 +2873,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
is_movable = ! LLFriendCardsManager::instance()
.isObjDirectDescendentOfCategory (inv_item, getCategory());
}
-
+
LLUUID favorites_id = model->findCategoryUUIDForType(LLAssetType::AT_FAVORITE);
// we can move item inside a folder only if this folder is Favorites. See EXT-719
@@ -2979,7 +2979,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID())
&& perm.allowTransferTo(gAgent.getID())))
// || gAgent.isGodlike())
-
+
{
accept = TRUE;
}
@@ -3010,7 +3010,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
LLNotifications::instance().forceResponse(params, 0);
}
}
-
+
}
else if(LLToolDragAndDrop::SOURCE_NOTECARD == source)
{
@@ -3063,11 +3063,11 @@ LLUIImagePtr LLTextureBridge::getIcon() const
{
return get_item_icon(LLAssetType::AT_TEXTURE, mInvType, 0, FALSE);
}
-
+
void LLTextureBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
-
+
if (item)
{
LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
@@ -3086,7 +3086,7 @@ LLUIImagePtr LLSoundBridge::getIcon() const
void LLSoundBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
-
+
if (item)
{
LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
@@ -3155,7 +3155,7 @@ void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
// +=================================================+
LLLandmarkBridge::LLLandmarkBridge(LLInventoryPanel* inventory, const LLUUID& uuid, U32 flags/* = 0x00*/) :
-LLItemBridge(inventory, uuid)
+LLItemBridge(inventory, uuid)
{
mVisited = FALSE;
if (flags & LLInventoryItem::II_FLAGS_LANDMARK_VISITED)
@@ -3244,7 +3244,7 @@ void LLLandmarkBridge::performAction(LLFolderView* folder, LLInventoryModel* mod
LLSideTray::getInstance()->showPanel("panel_places", key);
}
}
- else
+ else
{
LLItemBridge::performAction(folder, model, action);
}
@@ -3268,7 +3268,7 @@ static LLNotificationFunctorRegistration open_landmark_callback_reg("TeleportFro
void LLLandmarkBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
-
+
if (item)
{
LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
@@ -3376,7 +3376,7 @@ std::string LLCallingCardBridge::getLabelSuffix() const
void LLCallingCardBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
-
+
if (item)
{
LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
@@ -3515,7 +3515,7 @@ BOOL LLCallingCardBridge::removeItem()
LLAvatarActions::removeFriendDialog(getItem()->getCreatorUUID());
return FALSE;
}
- else
+ else
{
return LLItemBridge::removeItem();
}
@@ -3532,7 +3532,7 @@ LLUIImagePtr LLNotecardBridge::getIcon() const
void LLNotecardBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
-
+
if (item)
{
LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
@@ -3614,7 +3614,7 @@ void LLGestureBridge::performAction(LLFolderView* folder, LLInventoryModel* mode
void LLGestureBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
-
+
if (item)
{
LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
@@ -3716,7 +3716,7 @@ void LLAnimationBridge::performAction(LLFolderView* folder, LLInventoryModel* mo
LLPreviewAnim::e_activation_type activate = LLPreviewAnim::NONE;
if ("playworld" == action) activate = LLPreviewAnim::PLAY;
if ("playlocal" == action) activate = LLPreviewAnim::AUDITION;
-
+
LLPreviewAnim* preview = LLFloaterReg::showTypedInstance<LLPreviewAnim>("preview_anim", LLSD(mUUID));
if (preview)
{
@@ -3733,7 +3733,7 @@ void LLAnimationBridge::performAction(LLFolderView* folder, LLInventoryModel* mo
void LLAnimationBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
-
+
if (item)
{
LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
@@ -3841,7 +3841,7 @@ void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model
void LLObjectBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
-
+
if (item)
{
LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
@@ -3853,7 +3853,7 @@ void LLObjectBridge::openItem()
}
LLFontGL::StyleFlags LLObjectBridge::getLabelStyle() const
-{
+{
U8 font = LLFontGL::NORMAL;
LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
@@ -3867,7 +3867,7 @@ LLFontGL::StyleFlags LLObjectBridge::getLabelStyle() const
{
font |= LLFontGL::ITALIC;
}
-
+
return (LLFontGL::StyleFlags)font;
}
@@ -3878,7 +3878,7 @@ std::string LLObjectBridge::getLabelSuffix() const
{
std::string attachment_point_name = avatar->getAttachedPointName(mUUID);
LLStringUtil::toLower(attachment_point_name);
-
+
LLStringUtil::format_map_t args;
args["[ATTACHMENT_POINT]"] = attachment_point_name.c_str();
return LLItemBridge::getLabelSuffix() + LLTrans::getString("WornOnAttachmentPoint", args);
@@ -3925,7 +3925,7 @@ void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attach
bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response)
{
LLVOAvatar *avatarp = gAgent.getAvatarObject();
-
+
if (!avatarp->canAttachMoreObjects())
{
LLSD args;
@@ -3938,7 +3938,7 @@ bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& respon
if (option == 0/*YES*/)
{
LLViewerInventoryItem* itemp = gInventory.getItem(notification["payload"]["item_id"].asUUID());
-
+
if (itemp)
{
LLMessageSystem* msg = gMessageSystem;
@@ -3999,7 +3999,7 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
return;
}
-
+
if( avatarp->isWearingAttachment( mUUID ) )
{
items.push_back(std::string("Detach From Yourself"));
@@ -4023,13 +4023,13 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
LLMenuGL* attach_menu = menu.findChildMenuByName("Attach To", TRUE);
LLMenuGL* attach_hud_menu = menu.findChildMenuByName("Attach To HUD", TRUE);
LLVOAvatar *avatarp = gAgent.getAvatarObject();
- if (attach_menu
- && (attach_menu->getChildCount() == 0)
- && attach_hud_menu
- && (attach_hud_menu->getChildCount() == 0)
+ if (attach_menu
+ && (attach_menu->getChildCount() == 0)
+ && attach_hud_menu
+ && (attach_hud_menu->getChildCount() == 0)
&& avatarp)
{
- for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin();
+ for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin();
iter != avatarp->mAttachmentPoints.end(); )
{
LLVOAvatar::attachment_map_t::iterator curiter = iter++;
@@ -4110,7 +4110,7 @@ LLUIImagePtr LLLSLTextBridge::getIcon() const
void LLLSLTextBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
-
+
if (item)
{
LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
@@ -4146,7 +4146,7 @@ void wear_add_inventory_item_on_avatar( LLInventoryItem* item )
{
lldebugs << "wear_add_inventory_item_on_avatar( " << item->getName()
<< " )" << llendl;
-
+
LLWearableList::instance().getAsset(item->getAssetUUID(),
item->getName(),
item->getType(),
@@ -4160,8 +4160,8 @@ void remove_inventory_category_from_avatar( LLInventoryCategory* category )
if(!category) return;
lldebugs << "remove_inventory_category_from_avatar( " << category->getName()
<< " )" << llendl;
-
-
+
+
if( gFloaterCustomize )
{
gFloaterCustomize->askToSaveIfDirty(
@@ -4236,8 +4236,8 @@ void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_
}
}
}
-
-
+
+
if (obj_count > 0)
{
for(i = 0; i < obj_count; ++i)
@@ -4332,7 +4332,7 @@ void LLWearableBridge::performAction(LLFolderView* folder, LLInventoryModel* mod
{
LLViewerInventoryItem* item = getItem();
if (item)
- {
+ {
LLWearableList::instance().getAsset(item->getAssetUUID(),
item->getName(),
item->getType(),
@@ -4347,7 +4347,7 @@ void LLWearableBridge::performAction(LLFolderView* folder, LLInventoryModel* mod
void LLWearableBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
-
+
if (item)
{
LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
@@ -4431,7 +4431,7 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
getClipboardEntries(true, items, disabled_items, flags);
items.push_back(std::string("Wearable Separator"));
-
+
items.push_back(std::string("Wearable Wear"));
items.push_back(std::string("Wearable Add"));
items.push_back(std::string("Wearable Edit"));
@@ -4462,7 +4462,7 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
disabled_items.push_back(std::string("Wearable Add"));
}
else
- {
+ {
disabled_items.push_back(std::string("Take Off"));
}
break;
@@ -4501,7 +4501,7 @@ void LLWearableBridge::wearOnAvatar()
{
// Don't wear anything until initial wearables are loaded, can
// destroy clothing items.
- if (!gAgentWearables.areWearablesLoaded())
+ if (!gAgentWearables.areWearablesLoaded())
{
LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
return;
@@ -4532,7 +4532,7 @@ void LLWearableBridge::wearAddOnAvatar()
{
// Don't wear anything until initial wearables are loaded, can
// destroy clothing items.
- if (!gAgentWearables.areWearablesLoaded())
+ if (!gAgentWearables.areWearablesLoaded())
{
LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
return;
@@ -4620,7 +4620,7 @@ BOOL LLWearableBridge::canEditOnAvatar(void* user_data)
return (gAgentWearables.isWearingItem(self->mUUID));
}
-// static
+// static
void LLWearableBridge::onEditOnAvatar(void* user_data)
{
LLWearableBridge* self = (LLWearableBridge*)user_data;
@@ -4658,7 +4658,7 @@ BOOL LLWearableBridge::canRemoveFromAvatar(void* user_data)
return FALSE;
}
-// static
+// static
void LLWearableBridge::onRemoveFromAvatar(void* user_data)
{
LLWearableBridge* self = (LLWearableBridge*)user_data;
@@ -4689,7 +4689,7 @@ void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable,
if( gAgentWearables.isWearingItem( item_id ) )
{
EWearableType type = wearable->getType();
-
+
if( !(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR || type==WT_EYES ) ) //&&
//!((!gAgent.isTeen()) && ( type==WT_UNDERPANTS || type==WT_UNDERSHIRT )) )
{
@@ -4733,7 +4733,7 @@ LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_
case LLAssetType::AT_LANDMARK:
action = new LLLandmarkBridgeAction(uuid,model);
break;
-
+
case LLAssetType::AT_CALLINGCARD:
action = new LLCallingCardBridgeAction(uuid,model);
break;
@@ -4770,7 +4770,7 @@ LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_
return action;
}
-//static
+//static
void LLInvFVBridgeAction::doAction(LLAssetType::EType asset_type,
const LLUUID& uuid,LLInventoryModel* model)
{
@@ -4782,7 +4782,7 @@ void LLInvFVBridgeAction::doAction(LLAssetType::EType asset_type,
}
}
-//static
+//static
void LLInvFVBridgeAction::doAction(const LLUUID& uuid, LLInventoryModel* model)
{
LLAssetType::EType asset_type = model->getItem(uuid)->getType();
@@ -4801,8 +4801,8 @@ LLViewerInventoryItem* LLInvFVBridgeAction::getItem() const
return NULL;
}
-//virtual
-void LLTextureBridgeAction::doIt()
+//virtual
+void LLTextureBridgeAction::doIt()
{
if (getItem())
{
@@ -4813,20 +4813,20 @@ void LLTextureBridgeAction::doIt()
}
//virtual
-void LLSoundBridgeAction::doIt()
+void LLSoundBridgeAction::doIt()
{
LLViewerInventoryItem* item = getItem();
if(item)
{
LLFloaterReg::showInstance("preview_sound", LLSD(mUUID), TAKE_FOCUS_YES);
}
-
+
LLInvFVBridgeAction::doIt();
}
-//virtual
-void LLLandmarkBridgeAction::doIt()
+//virtual
+void LLLandmarkBridgeAction::doIt()
{
LLViewerInventoryItem* item = getItem();
if( item )
@@ -4842,8 +4842,8 @@ void LLLandmarkBridgeAction::doIt()
}
-//virtual
-void LLCallingCardBridgeAction::doIt()
+//virtual
+void LLCallingCardBridgeAction::doIt()
{
LLViewerInventoryItem* item = getItem();
if(item && item->getCreatorUUID().notNull())
@@ -4854,9 +4854,9 @@ void LLCallingCardBridgeAction::doIt()
LLInvFVBridgeAction::doIt();
}
-//virtual
-void
-LLNotecardBridgeAction::doIt()
+//virtual
+void
+LLNotecardBridgeAction::doIt()
{
LLViewerInventoryItem* item = getItem();
if (item)
@@ -4867,8 +4867,8 @@ LLNotecardBridgeAction::doIt()
LLInvFVBridgeAction::doIt();
}
-//virtual
-void LLGestureBridgeAction::doIt()
+//virtual
+void LLGestureBridgeAction::doIt()
{
LLViewerInventoryItem* item = getItem();
if (item)
@@ -4880,8 +4880,8 @@ void LLGestureBridgeAction::doIt()
LLInvFVBridgeAction::doIt();
}
-//virtual
-void LLAnimationBridgeAction::doIt()
+//virtual
+void LLAnimationBridgeAction::doIt()
{
LLViewerInventoryItem* item = getItem();
if (item)
@@ -4893,7 +4893,7 @@ void LLAnimationBridgeAction::doIt()
}
-//virtual
+//virtual
void LLObjectBridgeAction::doIt()
{
LLFloaterReg::showInstance("properties", mUUID);
@@ -4902,8 +4902,8 @@ void LLObjectBridgeAction::doIt()
}
-//virtual
-void LLLSLTextBridgeAction::doIt()
+//virtual
+void LLLSLTextBridgeAction::doIt()
{
LLViewerInventoryItem* item = getItem();
if (item)
@@ -4933,7 +4933,7 @@ void LLWearableBridgeAction::wearOnAvatar()
{
// Don't wear anything until initial wearables are loaded, can
// destroy clothing items.
- if (!gAgentWearables.areWearablesLoaded())
+ if (!gAgentWearables.areWearablesLoaded())
{
LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
return;
@@ -4960,7 +4960,7 @@ void LLWearableBridgeAction::wearOnAvatar()
}
}
-//virtual
+//virtual
void LLWearableBridgeAction::doIt()
{
if(isInTrash())
@@ -5036,7 +5036,7 @@ void LLLinkItemBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
items.push_back(std::string("Restore Item"));
}
else
- {
+ {
items.push_back(std::string("Delete"));
if (!isItemRemovable())
{
@@ -5086,7 +5086,7 @@ void LLLinkFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
items.push_back(std::string("Restore Item"));
}
else
- {
+ {
items.push_back(std::string("Goto Link"));
items.push_back(std::string("Delete"));
if (!isItemRemovable())
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index e49be83fbc..1d7cbde0d5 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -182,10 +182,12 @@ LLInventoryModel::~LLInventoryModel()
void LLInventoryModel::cleanupInventory()
{
empty();
- for (observer_list_t::iterator iter = mObservers.begin();
- iter != mObservers.end(); )
+ // Deleting one observer might erase others from the list, so always pop off the front
+ while (!mObservers.empty())
{
- LLInventoryObserver* observer = *iter++;
+ observer_list_t::iterator iter = mObservers.begin();
+ LLInventoryObserver* observer = *iter;
+ mObservers.erase(iter);
delete observer;
}
mObservers.clear();
diff --git a/indra/newview/lllandmarkactions.cpp b/indra/newview/lllandmarkactions.cpp
index b36b7cf50e..091346d3b4 100644
--- a/indra/newview/lllandmarkactions.cpp
+++ b/indra/newview/lllandmarkactions.cpp
@@ -348,7 +348,7 @@ LLLandmark* LLLandmarkActions::getLandmark(const LLUUID& landmarkInventoryItemID
{
LLViewerInventoryItem* item = gInventory.getItem(landmarkInventoryItemID);
if (NULL == item)
- return false;
+ return NULL;
const LLUUID& asset_id = item->getAssetUUID();
return gLandmarkList.getAsset(asset_id, NULL);
diff --git a/indra/newview/lllandmarkactions.h b/indra/newview/lllandmarkactions.h
index d651259790..32f05e702b 100644
--- a/indra/newview/lllandmarkactions.h
+++ b/indra/newview/lllandmarkactions.h
@@ -108,7 +108,7 @@ public:
/**
* @brief Retrieve a landmark from gLandmarkList by inventory item's id
*
- * @return pointer to loaded landmark from gLandmarkList or NULL if landmark does not exist.
+ * @return pointer to loaded landmark from gLandmarkList or NULL if landmark does not exist or wasn't loaded.
*/
static LLLandmark* getLandmark(const LLUUID& landmarkInventoryItemID);
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index 69214b5cab..a16ffe19c6 100644
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -36,6 +36,8 @@
#include "llappviewer.h"
#include "llfloaterchat.h"
#include "lltrans.h"
+#include "llviewercontrol.h"
+#include "llsdserialize.h"
const S32 LOG_RECALL_SIZE = 2048;
@@ -89,41 +91,53 @@ std::string LLLogChat::timestamp(bool withdate)
//static
-void LLLogChat::saveHistory(std::string filename, std::string line)
+void LLLogChat::saveHistory(const std::string& filename,
+ const std::string& from,
+ const LLUUID& from_id,
+ const std::string& line)
{
+ if (!gSavedPerAccountSettings.getBOOL("LogInstantMessages"))
+ return;
+
if(!filename.size())
{
llinfos << "Filename is Empty!" << llendl;
return;
}
- LLFILE* fp = LLFile::fopen(LLLogChat::makeLogFileName(filename), "a"); /*Flawfinder: ignore*/
- if (!fp)
+ llofstream file (LLLogChat::makeLogFileName(filename), std::ios_base::app);
+ if (!file.is_open())
{
llinfos << "Couldn't open chat history log!" << llendl;
+ return;
}
- else
- {
- fprintf(fp, "%s\n", line.c_str());
-
- fclose (fp);
- }
+
+ LLSD item;
+
+ if (gSavedPerAccountSettings.getBOOL("LogTimestamp"))
+ item["time"] = LLLogChat::timestamp(gSavedPerAccountSettings.getBOOL("LogTimestampDate"));
+
+ item["from"] = from;
+ item["from_id"] = from_id;
+ item["message"] = line;
+
+ file << LLSDOStreamer <LLSDNotationFormatter>(item) << std::endl;
+
+ file.close();
}
-void LLLogChat::loadHistory(std::string filename , void (*callback)(ELogLineType,std::string,void*), void* userdata)
+void LLLogChat::loadHistory(const std::string& filename, void (*callback)(ELogLineType, const LLSD&, void*), void* userdata)
{
if(!filename.size())
{
llwarns << "Filename is Empty!" << llendl;
return ;
}
-
+
LLFILE* fptr = LLFile::fopen(makeLogFileName(filename), "r"); /*Flawfinder: ignore*/
if (!fptr)
{
- //LLUIString message = LLTrans::getString("IM_logging_string");
- //callback(LOG_EMPTY,"IM_logging_string",userdata);
- callback(LOG_EMPTY,LLStringUtil::null,userdata);
+ callback(LOG_EMPTY, LLSD(), userdata);
return; //No previous conversation with this name.
}
else
@@ -143,6 +157,9 @@ void LLLogChat::loadHistory(std::string filename , void (*callback)(ELogLineType
}
}
+ // the parser's destructor is protected so we cannot create in the stack.
+ LLPointer<LLSDParser> parser = new LLSDNotationParser();
+
while ( fgets(buffer, LOG_RECALL_SIZE, fptr) && !feof(fptr) )
{
len = strlen(buffer) - 1; /*Flawfinder: ignore*/
@@ -150,14 +167,25 @@ void LLLogChat::loadHistory(std::string filename , void (*callback)(ELogLineType
if (!firstline)
{
- callback(LOG_LINE,std::string(buffer),userdata);
+ LLSD item;
+ std::string line(buffer);
+ std::istringstream iss(line);
+ if (parser->parse(iss, item, line.length()) == LLSDParser::PARSE_FAILURE)
+ {
+ item["message"] = line;
+ callback(LOG_LINE, item, userdata);
+ }
+ else
+ {
+ callback(LOG_LLSD, item, userdata);
+ }
}
else
{
firstline = FALSE;
}
}
- callback(LOG_END,LLStringUtil::null,userdata);
+ callback(LOG_END, LLSD(), userdata);
fclose(fptr);
}
diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h
index ad903b66fe..e252cd7d41 100644
--- a/indra/newview/lllogchat.h
+++ b/indra/newview/lllogchat.h
@@ -41,13 +41,18 @@ public:
enum ELogLineType {
LOG_EMPTY,
LOG_LINE,
+ LOG_LLSD,
LOG_END
};
static std::string timestamp(bool withdate = false);
static std::string makeLogFileName(std::string(filename));
- static void saveHistory(std::string filename, std::string line);
- static void loadHistory(std::string filename,
- void (*callback)(ELogLineType,std::string,void*),
+ static void saveHistory(const std::string& filename,
+ const std::string& from,
+ const LLUUID& from_id,
+ const std::string& line);
+
+ static void loadHistory(const std::string& filename,
+ void (*callback)(ELogLineType, const LLSD&, void*),
void* userdata);
private:
static std::string cleanFileName(std::string filename);
diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp
index 2b4e35208a..14da35594f 100644
--- a/indra/newview/llmoveview.cpp
+++ b/indra/newview/llmoveview.cpp
@@ -280,6 +280,14 @@ void LLFloaterMove::setMovementMode(const EMovementMode mode)
mCurrentMode = mode;
gAgent.setFlying(MM_FLY == mode);
+ // attempts to set avatar flying can not set it real flying in some cases.
+ // For ex. when avatar fell down & is standing up.
+ // So, no need to continue processing FLY mode. See EXT-1079
+ if (MM_FLY == mode && !gAgent.getFlying())
+ {
+ return;
+ }
+
switch (mode)
{
case MM_RUN:
diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp
index ff7f08bf97..36cf2c1aa8 100644
--- a/indra/newview/llmutelist.cpp
+++ b/indra/newview/llmutelist.cpp
@@ -65,7 +65,6 @@
#include "llworld.h" //for particle system banning
#include "llchat.h"
#include "llfloaterchat.h"
-#include "llimpanel.h"
#include "llimview.h"
#include "llnotifications.h"
#include "lluistring.h"
diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp
index b91e23eace..9a05812847 100644
--- a/indra/newview/llnavigationbar.cpp
+++ b/indra/newview/llnavigationbar.cpp
@@ -164,17 +164,6 @@ TODO:
- Load navbar height from saved settings (as it's done for status bar) or think of a better way.
*/
-S32 NAVIGATION_BAR_HEIGHT = 60; // *HACK
-LLNavigationBar* LLNavigationBar::sInstance = 0;
-
-LLNavigationBar* LLNavigationBar::getInstance()
-{
- if (!sInstance)
- sInstance = new LLNavigationBar();
-
- return sInstance;
-}
-
LLNavigationBar::LLNavigationBar()
: mTeleportHistoryMenu(NULL),
mBtnBack(NULL),
@@ -198,8 +187,6 @@ LLNavigationBar::LLNavigationBar()
LLNavigationBar::~LLNavigationBar()
{
mTeleportFinishConnection.disconnect();
- sInstance = 0;
-
LLSearchHistory::getInstance()->save();
}
@@ -272,6 +259,15 @@ void LLNavigationBar::draw()
onTeleportHistoryChanged();
mPurgeTPHistoryItems = false;
}
+
+ if (isBackgroundVisible())
+ {
+ static LLUICachedControl<S32> drop_shadow_floater ("DropShadowFloater", 0);
+ static LLUIColor color_drop_shadow = LLUIColorTable::instance().getColor("ColorDropShadow");
+ gl_drop_shadow(0, getRect().getHeight(), getRect().getWidth(), 0,
+ color_drop_shadow, drop_shadow_floater );
+ }
+
LLPanel::draw();
}
@@ -547,6 +543,15 @@ void LLNavigationBar::clearHistoryCache()
mPurgeTPHistoryItems= true;
}
+int LLNavigationBar::getDefNavBarHeight()
+{
+ return mDefaultNbRect.getHeight();
+}
+int LLNavigationBar::getDefFavBarHeight()
+{
+ return mDefaultFpRect.getHeight();
+}
+
void LLNavigationBar::showNavigationPanel(BOOL visible)
{
bool fpVisible = gSavedSettings.getBOOL("ShowNavbarFavoritesPanel");
diff --git a/indra/newview/llnavigationbar.h b/indra/newview/llnavigationbar.h
index 8a65cd24fa..8b625e7fa6 100644
--- a/indra/newview/llnavigationbar.h
+++ b/indra/newview/llnavigationbar.h
@@ -35,8 +35,6 @@
#include "llpanel.h"
-extern S32 NAVIGATION_BAR_HEIGHT;
-
class LLButton;
class LLLocationInputCtrl;
class LLMenuGL;
@@ -47,12 +45,12 @@ class LLSearchComboBox;
* Web browser-like navigation bar.
*/
class LLNavigationBar
-: public LLPanel
+ : public LLPanel, public LLSingleton<LLNavigationBar>
{
LOG_CLASS(LLNavigationBar);
-
+
public:
- static LLNavigationBar* getInstance();
+ LLNavigationBar();
virtual ~LLNavigationBar();
/*virtual*/ void draw();
@@ -63,9 +61,11 @@ public:
void showNavigationPanel(BOOL visible);
void showFavoritesPanel(BOOL visible);
+
+ int getDefNavBarHeight();
+ int getDefFavBarHeight();
private:
- LLNavigationBar();
void rebuildTeleportHistoryMenu();
void showTeleportHistoryMenu();
@@ -91,8 +91,6 @@ private:
void fillSearchComboBox();
- static LLNavigationBar *sInstance;
-
LLMenuGL* mTeleportHistoryMenu;
LLButton* mBtnBack;
LLButton* mBtnForward;
diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp
index 148f72703c..12638ab855 100644
--- a/indra/newview/llnearbychat.cpp
+++ b/indra/newview/llnearbychat.cpp
@@ -170,22 +170,6 @@ LLColor4 nearbychat_get_text_color(const LLChat& chat)
return text_color;
}
-std::string formatCurrentTime()
-{
- time_t utc_time;
- utc_time = time_corrected();
- std::string timeStr ="["+ LLTrans::getString("TimeHour")+"]:["
- +LLTrans::getString("TimeMin")+"] ";
-
- LLSD substitution;
-
- substitution["datetime"] = (S32) utc_time;
- LLStringUtil::format (timeStr, substitution);
-
- return timeStr;
-}
-
-
void LLNearbyChat::add_timestamped_line(const LLChat& chat, const LLColor4& color)
{
S32 font_size = gSavedSettings.getS32("ChatFontSize");
@@ -210,16 +194,14 @@ void LLNearbyChat::add_timestamped_line(const LLChat& chat, const LLColor4& colo
style_params.font(fontp);
LLUUID uuid = chat.mFromID;
std::string from = chat.mFromName;
- std::string time = formatCurrentTime();
std::string message = chat.mText;
- mChatHistory->appendWidgetMessage(uuid, from, time, message, style_params);
+ mChatHistory->appendWidgetMessage(chat, style_params);
}
void LLNearbyChat::addMessage(const LLChat& chat)
{
LLColor4 color = nearbychat_get_text_color(chat);
-
if (chat.mChatType == CHAT_TYPE_DEBUG_MSG)
{
if(gSavedSettings.getBOOL("ShowScriptErrors") == FALSE)
diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp
index 5fa97926a5..217007fb15 100644
--- a/indra/newview/llnearbychatbar.cpp
+++ b/indra/newview/llnearbychatbar.cpp
@@ -45,6 +45,7 @@
#include "llviewerstats.h"
#include "llcommandhandler.h"
#include "llviewercontrol.h"
+#include "llnavigationbar.h"
S32 LLNearbyChatBar::sLastSpecialChatChannel = 0;
@@ -177,6 +178,31 @@ void LLGestureComboBox::draw()
LLComboBox::draw();
}
+//virtual
+void LLGestureComboBox::showList()
+{
+ LLComboBox::showList();
+
+ // Calculating amount of space between the navigation bar and gestures combo
+ LLNavigationBar* nb = LLNavigationBar::getInstance();
+ S32 x, nb_bottom;
+ nb->localPointToScreen(0, 0, &x, &nb_bottom);
+
+ S32 list_bottom;
+ mList->localPointToScreen(0, 0, &x, &list_bottom);
+
+ S32 max_height = nb_bottom - list_bottom;
+
+ LLRect rect = mList->getRect();
+ // List overlapped navigation bar, downsize it
+ if (rect.getHeight() > max_height)
+ {
+ rect.setOriginAndSize(rect.mLeft, rect.mBottom, rect.getWidth(), max_height);
+ mList->setRect(rect);
+ mList->reshape(rect.getWidth(), rect.getHeight());
+ }
+}
+
LLNearbyChatBar::LLNearbyChatBar()
: LLPanel()
, mChatBox(NULL)
diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h
index b902ff86cc..06204e6367 100644
--- a/indra/newview/llnearbychatbar.h
+++ b/indra/newview/llnearbychatbar.h
@@ -40,7 +40,7 @@
#include "llchiclet.h"
#include "llvoiceclient.h"
#include "lloutputmonitorctrl.h"
-#include "llfloateractivespeakers.h"
+#include "llspeakers.h"
class LLGestureComboBox
: public LLComboBox
@@ -62,6 +62,9 @@ public:
virtual void changed() { refreshGestures(); }
protected:
+
+ virtual void showList();
+
LLFrameTimer mGestureLabelTimer;
std::vector<LLMultiGesture*> mGestures;
std::string mLabel;
diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp
index 7239f49b7f..543198c1d2 100644
--- a/indra/newview/llnotificationtiphandler.cpp
+++ b/indra/newview/llnotificationtiphandler.cpp
@@ -86,6 +86,20 @@ bool LLTipHandler::processNotification(const LLSD& notify)
if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change")
{
+ // archive message in nearby chat
+ LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD());
+ if(nearby_chat)
+ {
+ LLChat chat_msg(notification->getMessage());
+ nearby_chat->addMessage(chat_msg);
+
+ // don't show toast if Nearby Chat is opened
+ if (nearby_chat->getVisible())
+ {
+ return true;
+ }
+ }
+
LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification);
LLToast::Params p;
@@ -99,14 +113,6 @@ bool LLTipHandler::processNotification(const LLSD& notify)
LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel);
if(channel)
channel->addToast(p);
-
- // archive message in nearby chat
- LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD());
- if(nearby_chat)
- {
- LLChat chat_msg(notification->getMessage());
- nearby_chat->addMessage(chat_msg);
- }
}
else if (notify["sigtype"].asString() == "delete")
{
diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp
index 6eed956eb8..f9eeaf1e9e 100644
--- a/indra/newview/llpanelimcontrolpanel.cpp
+++ b/indra/newview/llpanelimcontrolpanel.cpp
@@ -34,6 +34,7 @@
#include "llpanelimcontrolpanel.h"
+#include "llagent.h"
#include "llavataractions.h"
#include "llavatariconctrl.h"
#include "llbutton.h"
@@ -41,6 +42,53 @@
#include "llavatarlist.h"
#include "llparticipantlist.h"
#include "llimview.h"
+#include "llvoicechannel.h"
+
+void LLPanelChatControlPanel::onCallButtonClicked()
+{
+ gIMMgr->startCall(mSessionId);
+}
+
+void LLPanelChatControlPanel::onEndCallButtonClicked()
+{
+ gIMMgr->endCall(mSessionId);
+}
+
+BOOL LLPanelChatControlPanel::postBuild()
+{
+ childSetAction("call_btn", boost::bind(&LLPanelChatControlPanel::onCallButtonClicked, this));
+ childSetAction("end_call_btn", boost::bind(&LLPanelChatControlPanel::onEndCallButtonClicked, this));
+
+ return TRUE;
+}
+
+void LLPanelChatControlPanel::draw()
+{
+ // hide/show start call and end call buttons
+ bool voice_enabled = LLVoiceClient::voiceEnabled();
+
+ LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(mSessionId);
+ if (!session) return;
+
+ LLVoiceChannel* voice_channel = session->mVoiceChannel;
+ if (voice_channel && voice_enabled)
+ {
+ childSetVisible("end_call_btn", voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED);
+ childSetVisible("call_btn", voice_channel->getState() < LLVoiceChannel::STATE_CALL_STARTED);
+ }
+
+ bool session_initialized = session->mSessionInitialized;
+ bool callback_enabled = session->mCallBackEnabled;
+ LLViewerRegion* region = gAgent.getRegion();
+
+ BOOL enable_connect = (region && region->getCapability("ChatSessionRequest") != "")
+ && session_initialized
+ && voice_enabled
+ && callback_enabled;
+ childSetEnabled("call_btn", enable_connect);
+
+ LLPanel::draw();
+}
LLPanelIMControlPanel::LLPanelIMControlPanel()
{
@@ -54,11 +102,11 @@ BOOL LLPanelIMControlPanel::postBuild()
{
childSetAction("view_profile_btn", boost::bind(&LLPanelIMControlPanel::onViewProfileButtonClicked, this));
childSetAction("add_friend_btn", boost::bind(&LLPanelIMControlPanel::onAddFriendButtonClicked, this));
- childSetAction("call_btn", boost::bind(&LLPanelIMControlPanel::onCallButtonClicked, this));
+
childSetAction("share_btn", boost::bind(&LLPanelIMControlPanel::onShareButtonClicked, this));
childSetEnabled("add_friend_btn", !LLAvatarActions::isFriend(getChild<LLAvatarIconCtrl>("avatar_icon")->getAvatarId()));
-
- return TRUE;
+
+ return LLPanelChatControlPanel::postBuild();
}
void LLPanelIMControlPanel::onViewProfileButtonClicked()
@@ -73,22 +121,29 @@ void LLPanelIMControlPanel::onAddFriendButtonClicked()
LLAvatarActions::requestFriendshipDialog(avatar_icon->getAvatarId(), full_name);
}
-void LLPanelIMControlPanel::onCallButtonClicked()
-{
- // *TODO: Implement
-}
-
void LLPanelIMControlPanel::onShareButtonClicked()
{
// *TODO: Implement
}
-void LLPanelIMControlPanel::setID(const LLUUID& avatar_id)
+void LLPanelIMControlPanel::setSessionId(const LLUUID& session_id)
{
+ LLPanelChatControlPanel::setSessionId(session_id);
+
+ LLIMModel& im_model = LLIMModel::instance();
+
+ LLUUID avatar_id = im_model.getOtherParticipantID(session_id);
+
// Disable "Add friend" button for friends.
childSetEnabled("add_friend_btn", !LLAvatarActions::isFriend(avatar_id));
getChild<LLAvatarIconCtrl>("avatar_icon")->setValue(avatar_id);
+
+ // Disable profile button if participant is not realy SL avatar
+ LLIMModel::LLIMSession* im_session =
+ im_model.findIMSession(session_id);
+ if( im_session && !im_session->mOtherParticipantIsAvatar )
+ childSetEnabled("view_profile_btn", FALSE);
}
@@ -100,12 +155,11 @@ LLPanelGroupControlPanel::LLPanelGroupControlPanel(const LLUUID& session_id)
BOOL LLPanelGroupControlPanel::postBuild()
{
childSetAction("group_info_btn", boost::bind(&LLPanelGroupControlPanel::onGroupInfoButtonClicked, this));
- childSetAction("call_btn", boost::bind(&LLPanelGroupControlPanel::onCallButtonClicked, this));
mAvatarList = getChild<LLAvatarList>("speakers_list");
mParticipantList = new LLParticipantList(mSpeakerManager, mAvatarList);
- return TRUE;
+ return LLPanelChatControlPanel::postBuild();
}
LLPanelGroupControlPanel::~LLPanelGroupControlPanel()
@@ -127,13 +181,23 @@ void LLPanelGroupControlPanel::onGroupInfoButtonClicked()
}
-void LLPanelGroupControlPanel::onCallButtonClicked()
+void LLPanelGroupControlPanel::setSessionId(const LLUUID& session_id)
{
- // *TODO: Implement
+ LLPanelChatControlPanel::setSessionId(session_id);
+
+ mGroupID = LLIMModel::getInstance()->getOtherParticipantID(session_id);
}
-void LLPanelGroupControlPanel::setID(const LLUUID& id)
+LLPanelAdHocControlPanel::LLPanelAdHocControlPanel(const LLUUID& session_id):LLPanelGroupControlPanel(session_id)
+{
+}
+
+BOOL LLPanelAdHocControlPanel::postBuild()
{
- mGroupID = id;
+ mAvatarList = getChild<LLAvatarList>("speakers_list");
+ mParticipantList = new LLParticipantList(mSpeakerManager, mAvatarList);
+
+ return LLPanelChatControlPanel::postBuild();
}
+
diff --git a/indra/newview/llpanelimcontrolpanel.h b/indra/newview/llpanelimcontrolpanel.h
index 138b1630c4..220b7b14ba 100644
--- a/indra/newview/llpanelimcontrolpanel.h
+++ b/indra/newview/llpanelimcontrolpanel.h
@@ -45,8 +45,16 @@ public:
LLPanelChatControlPanel() {};
~LLPanelChatControlPanel() {};
- // sets the group or avatar UUID
- virtual void setID(const LLUUID& avatar_id)= 0;
+ virtual BOOL postBuild();
+ virtual void draw();
+
+ void onCallButtonClicked();
+ void onEndCallButtonClicked();
+
+ virtual void setSessionId(const LLUUID& session_id) { mSessionId = session_id; }
+
+private:
+ LLUUID mSessionId;
};
@@ -58,13 +66,14 @@ public:
BOOL postBuild();
- void setID(const LLUUID& avatar_id);
+ void setSessionId(const LLUUID& session_id);
private:
void onViewProfileButtonClicked();
void onAddFriendButtonClicked();
- void onCallButtonClicked();
void onShareButtonClicked();
+
+ LLUUID mAvatarID;
};
@@ -76,19 +85,26 @@ public:
BOOL postBuild();
- void setID(const LLUUID& id);
+ void setSessionId(const LLUUID& session_id);
/*virtual*/ void draw();
-private:
- void onGroupInfoButtonClicked();
- void onCallButtonClicked();
-
+protected:
LLUUID mGroupID;
LLSpeakerMgr* mSpeakerManager;
LLAvatarList* mAvatarList;
LLParticipantList* mParticipantList;
+
+private:
+ void onGroupInfoButtonClicked();
};
+class LLPanelAdHocControlPanel : public LLPanelGroupControlPanel
+{
+public:
+ LLPanelAdHocControlPanel(const LLUUID& session_id);
+
+ BOOL postBuild();
+};
#endif // LL_LLPANELIMCONTROLPANEL_H
diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index 83fb147a49..3d0db71045 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -38,10 +38,12 @@
#include "llsdutil.h"
#include "llsdutil_math.h"
+#include "llaccordionctrl.h"
#include "llaccordionctrltab.h"
#include "llagent.h"
#include "llagentpicksinfo.h"
#include "llagentui.h"
+#include "llcallbacklist.h"
#include "lldndbutton.h"
#include "llfloaterworldmap.h"
#include "llfolderviewitem.h"
@@ -56,7 +58,7 @@
//static LLRegisterPanelClassWrapper<LLLandmarksPanel> t_landmarks("panel_landmarks");
static const std::string OPTIONS_BUTTON_NAME = "options_gear_btn";
-static const std::string ADD_LANDMARK_BUTTON_NAME = "add_landmark_btn";
+static const std::string ADD_BUTTON_NAME = "add_btn";
static const std::string ADD_FOLDER_BUTTON_NAME = "add_folder_btn";
static const std::string TRASH_BUTTON_NAME = "trash_btn";
@@ -75,6 +77,7 @@ LLLandmarksPanel::LLLandmarksPanel()
, mListCommands(NULL)
, mGearFolderMenu(NULL)
, mGearLandmarkMenu(NULL)
+ , mDirtyFilter(false)
{
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_landmarks.xml");
}
@@ -98,16 +101,37 @@ BOOL LLLandmarksPanel::postBuild()
initMyInventroyPanel();
initLibraryInventroyPanel();
+ gIdleCallbacks.addFunction(LLLandmarksPanel::doIdle, this);
return TRUE;
}
// virtual
void LLLandmarksPanel::onSearchEdit(const std::string& string)
{
+ static std::string prev_string("");
+
+ if (prev_string == string) return;
+
+ // show all folders in Landmarks Accordion for empty filter
+ mLandmarksInventoryPanel->setShowFolderState(string.empty() ?
+ LLInventoryFilter::SHOW_ALL_FOLDERS :
+ LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS
+ );
+
filter_list(mFavoritesInventoryPanel, string);
filter_list(mLandmarksInventoryPanel, string);
filter_list(mMyInventoryPanel, string);
filter_list(mLibraryInventoryPanel, string);
+
+ prev_string = string;
+ mDirtyFilter = true;
+
+ // give FolderView a chance to be refreshed. So, made all accordions visible
+ for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter)
+ {
+ LLAccordionCtrlTab* tab = *iter;
+ tab->setVisible(true);
+ }
}
// virtual
@@ -300,6 +324,8 @@ void LLLandmarksPanel::processParcelInfo(const LLParcelData& parcel_data)
panel_pick, panel_places,params));
panel_pick->setSaveCallback(boost::bind(&LLLandmarksPanel::onPickPanelExit,this,
panel_pick, panel_places,params));
+ panel_pick->setCancelCallback(boost::bind(&LLLandmarksPanel::onPickPanelExit,this,
+ panel_pick, panel_places,params));
}
}
}
@@ -389,6 +415,7 @@ void LLLandmarksPanel::initLandmarksPanel(LLInventorySubTreePanel* inventory_lis
void LLLandmarksPanel::initAccordion(const std::string& accordion_tab_name, LLInventorySubTreePanel* inventory_list)
{
LLAccordionCtrlTab* accordion_tab = getChild<LLAccordionCtrlTab>(accordion_tab_name);
+ mAccordionTabs.push_back(accordion_tab);
accordion_tab->setDropDownStateChangedCallback(
boost::bind(&LLLandmarksPanel::onAccordionExpandedCollapsed, this, _2, inventory_list));
}
@@ -433,11 +460,11 @@ void LLLandmarksPanel::initListCommandsHandlers()
mListCommands = getChild<LLPanel>("bottom_panel");
mListCommands->childSetAction(OPTIONS_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onActionsButtonClick, this));
- mListCommands->childSetAction(ADD_LANDMARK_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onAddLandmarkButtonClick, this));
- mListCommands->childSetAction(ADD_FOLDER_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onAddFolderButtonClick, this));
mListCommands->childSetAction(TRASH_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onTrashButtonClick, this));
+ mListCommands->getChild<LLButton>(ADD_BUTTON_NAME)->setHeldDownCallback(boost::bind(&LLLandmarksPanel::onAddButtonHeldDown, this));
+ static const LLSD add_landmark_command("add_landmark");
+ mListCommands->childSetAction(ADD_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onAddAction, this, add_landmark_command));
-
LLDragAndDropButton* trash_btn = mListCommands->getChild<LLDragAndDropButton>(TRASH_BUTTON_NAME);
trash_btn->setDragAndDropHandler(boost::bind(&LLLandmarksPanel::handleDragAndDropToTrash, this
, _4 // BOOL drop
@@ -453,6 +480,7 @@ void LLLandmarksPanel::initListCommandsHandlers()
mEnableCallbackRegistrar.add("Places.LandmarksGear.Enable", boost::bind(&LLLandmarksPanel::isActionEnabled, this, _2));
mGearLandmarkMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_places_gear_landmark.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
mGearFolderMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_places_gear_folder.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ mMenuAdd = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_place_add_button.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
}
@@ -488,52 +516,26 @@ void LLLandmarksPanel::onActionsButtonClick()
mGearFolderMenu->getChild<LLMenuItemCallGL>("collapse")->setVisible(cur_item->isOpen());
menu = mGearFolderMenu;
}
- if(menu)
- {
- menu->buildDrawLabels();
- menu->updateParent(LLMenuGL::sMenuContainer);
- LLView* actions_btn = getChild<LLView>(OPTIONS_BUTTON_NAME);
- S32 menu_x, menu_y;
- actions_btn->localPointToOtherView(0,actions_btn->getRect().getHeight(),&menu_x,&menu_y, this);
- menu_y += menu->getRect().getHeight();
- LLMenuGL::showPopup(this, menu, menu_x,menu_y);
- }
+ showActionMenu(menu,OPTIONS_BUTTON_NAME);
}
-void LLLandmarksPanel::onAddLandmarkButtonClick() const
+void LLLandmarksPanel::onAddButtonHeldDown()
{
- if(LLLandmarkActions::landmarkAlreadyExists())
- {
- std::string location;
- LLAgentUI::buildLocationString(location, LLAgentUI::LOCATION_FORMAT_FULL);
- llwarns<<" Landmark already exists at location: "<< location<<llendl;
- return;
- }
- LLSideTray::getInstance()->showPanel("panel_places", LLSD().insert("type", "create_landmark"));
+ showActionMenu(mMenuAdd,ADD_BUTTON_NAME);
}
-void LLLandmarksPanel::onAddFolderButtonClick() const
+void LLLandmarksPanel::showActionMenu(LLMenuGL* menu, std::string spawning_view_name)
{
- LLFolderViewItem* item = getCurSelectedItem();
- if(item && mCurrentSelectedList == mLandmarksInventoryPanel)
+ if (menu)
{
- LLFolderViewEventListener* folder_bridge = NULL;
- if(item-> getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK)
- {
- // for a landmark get parent folder bridge
- folder_bridge = item->getParentFolder()->getListener();
- }
- else if (item-> getListener()->getInventoryType() == LLInventoryType::IT_CATEGORY)
- {
- // for a folder get its own bridge
- folder_bridge = item->getListener();
- }
-
- menu_create_inventory_item(mCurrentSelectedList->getRootFolder()
- , dynamic_cast<LLFolderBridge*>(folder_bridge)
- , LLSD("category")
- , gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK)
- );
+ menu->buildDrawLabels();
+ menu->updateParent(LLMenuGL::sMenuContainer);
+ LLView* spawning_view = getChild<LLView> (spawning_view_name);
+ S32 menu_x, menu_y;
+ //show menu in co-ordinates of panel
+ spawning_view->localPointToOtherView(0, spawning_view->getRect().getHeight(), &menu_x, &menu_y, this);
+ menu_y += menu->getRect().getHeight();
+ LLMenuGL::showPopup(this, menu, menu_x, menu_y);
}
}
@@ -547,11 +549,39 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const
std::string command_name = userdata.asString();
if("add_landmark" == command_name)
{
- onAddLandmarkButtonClick();
+ if(LLLandmarkActions::landmarkAlreadyExists())
+ {
+ std::string location;
+ LLAgentUI::buildLocationString(location, LLAgentUI::LOCATION_FORMAT_FULL);
+ llwarns<<" Landmark already exists at location: "<< location<<llendl;
+ return;
+ }
+ LLSideTray::getInstance()->showPanel("panel_places", LLSD().insert("type", "create_landmark"));
}
else if ("category" == command_name)
{
- onAddFolderButtonClick();
+ LLFolderViewItem* item = getCurSelectedItem();
+ if (item && mCurrentSelectedList == mLandmarksInventoryPanel)
+ {
+ LLFolderViewEventListener* folder_bridge = NULL;
+ if (item-> getListener()->getInventoryType()
+ == LLInventoryType::IT_LANDMARK)
+ {
+ // for a landmark get parent folder bridge
+ folder_bridge = item->getParentFolder()->getListener();
+ }
+ else if (item-> getListener()->getInventoryType()
+ == LLInventoryType::IT_CATEGORY)
+ {
+ // for a folder get its own bridge
+ folder_bridge = item->getListener();
+ }
+
+ menu_create_inventory_item(mCurrentSelectedList->getRootFolder(),
+ dynamic_cast<LLFolderBridge*> (folder_bridge), LLSD(
+ "category"), gInventory.findCategoryUUIDForType(
+ LLAssetType::AT_LANDMARK));
+ }
}
}
@@ -854,6 +884,43 @@ bool LLLandmarksPanel::handleDragAndDropToTrash(BOOL drop, EDragAndDropType carg
}
+void LLLandmarksPanel::doIdle(void* landmarks_panel)
+{
+ LLLandmarksPanel* panel = (LLLandmarksPanel* ) landmarks_panel;
+
+ if (panel->mDirtyFilter)
+ {
+ panel->updateFilteredAccordions();
+ }
+
+}
+
+void LLLandmarksPanel::updateFilteredAccordions()
+{
+ LLInventoryPanel* inventory_list = NULL;
+ LLAccordionCtrlTab* accordion_tab = NULL;
+ for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter)
+ {
+ accordion_tab = *iter;
+ inventory_list = dynamic_cast<LLInventorySubTreePanel*> (accordion_tab->getAccordionView());
+ if (NULL == inventory_list) continue;
+ LLFolderView* fv = inventory_list->getRootFolder();
+
+ bool has_visible_children = fv->hasVisibleChildren();
+
+ accordion_tab->setVisible(has_visible_children);
+ }
+
+ // we have to arrange accordion tabs for cases when filter string is less restrictive but
+ // all items are still filtered.
+ static LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("landmarks_accordion");
+ accordion->arrange();
+
+ // now filter state is applied to accordion tabs
+ mDirtyFilter = false;
+}
+
+
//////////////////////////////////////////////////////////////////////////
// HELPER FUNCTIONS
//////////////////////////////////////////////////////////////////////////
diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h
index 47c9f7647c..0e7abb4865 100644
--- a/indra/newview/llpanellandmarks.h
+++ b/indra/newview/llpanellandmarks.h
@@ -41,6 +41,7 @@
#include "llpanelpick.h"
#include "llremoteparcelrequest.h"
+class LLAccordionCtrlTab;
class LLFolderViewItem;
class LLMenuGL;
class LLInventoryPanel;
@@ -90,8 +91,8 @@ private:
void initListCommandsHandlers();
void updateListCommands();
void onActionsButtonClick();
- void onAddLandmarkButtonClick() const;
- void onAddFolderButtonClick() const;
+ void showActionMenu(LLMenuGL* menu, std::string spawning_view_name);
+ void onAddButtonHeldDown();
void onTrashButtonClick() const;
void onAddAction(const LLSD& command_name) const;
void onClipboardAction(const LLSD& command_name) const;
@@ -114,6 +115,18 @@ private:
*/
bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept);
+ /**
+ * Static callback for gIdleCallbacks to perform actions out of drawing
+ */
+ static void doIdle(void* landmarks_panel);
+
+ /**
+ * Updates accordions according to filtered items in lists.
+ *
+ * It hides accordion for empty lists
+ */
+ void updateFilteredAccordions();
+
private:
LLInventorySubTreePanel* mFavoritesInventoryPanel;
LLInventorySubTreePanel* mLandmarksInventoryPanel;
@@ -121,10 +134,15 @@ private:
LLInventorySubTreePanel* mLibraryInventoryPanel;
LLMenuGL* mGearLandmarkMenu;
LLMenuGL* mGearFolderMenu;
+ LLMenuGL* mMenuAdd;
LLInventorySubTreePanel* mCurrentSelectedList;
LLPanel* mListCommands;
bool mSortByDate;
+ bool mDirtyFilter;
+
+ typedef std::vector<LLAccordionCtrlTab*> accordion_tabs_t;
+ accordion_tabs_t mAccordionTabs;
};
#endif //LL_LLPANELLANDMARKS_H
diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp
index 61d66873ea..4580eeb336 100644
--- a/indra/newview/llpanelpeople.cpp
+++ b/indra/newview/llpanelpeople.cpp
@@ -413,13 +413,17 @@ BOOL LLPanelPeople::postBuild()
mOnlineFriendList = getChild<LLPanel>(FRIENDS_TAB_NAME)->getChild<LLAvatarList>("avatars_online");
mAllFriendList = getChild<LLPanel>(FRIENDS_TAB_NAME)->getChild<LLAvatarList>("avatars_all");
mOnlineFriendList->setNoItemsCommentText(getString("no_friends_online"));
+ mOnlineFriendList->setShowIcons("FriendsListShowIcons");
mAllFriendList->setNoItemsCommentText(getString("no_friends"));
+ mAllFriendList->setShowIcons("FriendsListShowIcons");
mNearbyList = getChild<LLPanel>(NEARBY_TAB_NAME)->getChild<LLAvatarList>("avatar_list");
mNearbyList->setNoItemsCommentText(getString("no_one_near"));
+ mNearbyList->setShowIcons("NearbyListShowIcons");
mRecentList = getChild<LLPanel>(RECENT_TAB_NAME)->getChild<LLAvatarList>("avatar_list");
mRecentList->setNoItemsCommentText(getString("no_people"));
+ mRecentList->setShowIcons("RecentListShowIcons");
mGroupList = getChild<LLGroupList>("group_list");
mGroupList->setNoItemsCommentText(getString("no_groups"));
@@ -611,6 +615,10 @@ void LLPanelPeople::updateButtons()
bool recent_tab_active = (cur_tab == RECENT_TAB_NAME);
LLUUID selected_id;
+ std::vector<LLUUID> selected_uuids;
+ getCurrentItemIDs(selected_uuids);
+ bool item_selected = (selected_uuids.size() == 1);
+
buttonSetVisible("group_info_btn", group_tab_active);
buttonSetVisible("chat_btn", group_tab_active);
buttonSetVisible("add_friend_btn", nearby_tab_active || recent_tab_active);
@@ -621,7 +629,6 @@ void LLPanelPeople::updateButtons()
if (group_tab_active)
{
- bool item_selected = mGroupList->getSelectedItem() != NULL;
bool cur_group_active = true;
if (item_selected)
@@ -629,7 +636,7 @@ void LLPanelPeople::updateButtons()
selected_id = mGroupList->getSelectedUUID();
cur_group_active = (gAgent.getGroupID() == selected_id);
}
-
+
LLPanel* groups_panel = mTabContainer->getCurrentPanel();
groups_panel->childSetEnabled("activate_btn", item_selected && !cur_group_active); // "none" or a non-active group selected
groups_panel->childSetEnabled("plus_btn", item_selected);
@@ -640,18 +647,18 @@ void LLPanelPeople::updateButtons()
bool is_friend = true;
// Check whether selected avatar is our friend.
- if ((selected_id = getCurrentItemID()).notNull())
+ if (item_selected)
{
+ selected_id = selected_uuids.front();
is_friend = LLAvatarTracker::instance().getBuddyInfo(selected_id) != NULL;
}
childSetEnabled("add_friend_btn", !is_friend);
}
- bool item_selected = selected_id.notNull();
buttonSetEnabled("teleport_btn", friends_tab_active && item_selected);
buttonSetEnabled("view_profile_btn", item_selected);
- buttonSetEnabled("im_btn", item_selected);
+ buttonSetEnabled("im_btn", (selected_uuids.size() >= 1)); // allow starting the friends conference for multiple selection
buttonSetEnabled("call_btn", item_selected && false); // not implemented yet
buttonSetEnabled("share_btn", item_selected && false); // not implemented yet
buttonSetEnabled("group_info_btn", item_selected);
@@ -877,7 +884,17 @@ void LLPanelPeople::onAddFriendWizButtonClicked()
void LLPanelPeople::onDeleteFriendButtonClicked()
{
- LLAvatarActions::removeFriendDialog(getCurrentItemID());
+ std::vector<LLUUID> selected_uuids;
+ getCurrentItemIDs(selected_uuids);
+
+ if (selected_uuids.size() == 1)
+ {
+ LLAvatarActions::removeFriendDialog( selected_uuids.front() );
+ }
+ else if (selected_uuids.size() > 1)
+ {
+ LLAvatarActions::removeFriendsDialog( selected_uuids );
+ }
}
void LLPanelPeople::onGroupInfoButtonClicked()
@@ -963,6 +980,8 @@ void LLPanelPeople::onFriendsViewSortMenuItemClicked(const LLSD& userdata)
}
else if (chosen_item == "view_icons")
{
+ mAllFriendList->toggleIcons();
+ mOnlineFriendList->toggleIcons();
}
else if (chosen_item == "organize_offline")
{
@@ -992,6 +1011,7 @@ void LLPanelPeople::onNearbyViewSortMenuItemClicked(const LLSD& userdata)
}
else if (chosen_item == "view_icons")
{
+ mNearbyList->toggleIcons();
}
else if (chosen_item == "sort_distance")
{
@@ -1011,7 +1031,7 @@ void LLPanelPeople::onRecentViewSortMenuItemClicked(const LLSD& userdata)
}
else if (chosen_item == "view_icons")
{
- // *TODO: implement showing/hiding icons
+ mRecentList->toggleIcons();
}
}
diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp
index cb9f7184f0..5af27a5ec1 100644
--- a/indra/newview/llpanelplaceinfo.cpp
+++ b/indra/newview/llpanelplaceinfo.cpp
@@ -55,6 +55,8 @@
#include "llagent.h"
#include "llagentui.h"
#include "llavatarpropertiesprocessor.h"
+#include "llcallbacklist.h"
+#include "llexpandabletextbox.h"
#include "llfloaterworldmap.h"
#include "llfloaterbuycurrency.h"
#include "llinventorymodel.h"
@@ -65,6 +67,7 @@
#include "llviewerinventory.h"
#include "llviewerparcelmgr.h"
#include "llviewerregion.h"
+#include "llviewercontrol.h"
#include "llviewertexteditor.h"
#include "llworldmap.h"
#include "llsdutil_math.h"
@@ -76,7 +79,6 @@
typedef std::pair<LLUUID, std::string> folder_pair_t;
static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right);
-static std::string getFullFolderName(const LLViewerInventoryCategory* cat);
static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats);
static LLRegisterPanelClassWrapper<LLPanelPlaceInfo> t_place_info("panel_place_info");
@@ -111,7 +113,7 @@ BOOL LLPanelPlaceInfo::postBuild()
mForSalePanel = getChild<LLPanel>("for_sale_panel");
mYouAreHerePanel = getChild<LLPanel>("here_panel");
- LLViewerParcelMgr::getInstance()->addAgentParcelChangedCallback(boost::bind(&LLPanelPlaceInfo::updateYouAreHereBanner,this));
+ gIdleCallbacks.addFunction(&LLPanelPlaceInfo::updateYouAreHereBanner, this);
//Icon value should contain sale price of last selected parcel.
mForSalePanel->getChild<LLIconCtrl>("icon_for_sale")->
@@ -120,7 +122,7 @@ BOOL LLPanelPlaceInfo::postBuild()
mSnapshotCtrl = getChild<LLTextureCtrl>("logo");
mRegionName = getChild<LLTextBox>("region_title");
mParcelName = getChild<LLTextBox>("parcel_title");
- mDescEditor = getChild<LLTextEditor>("description");
+ mDescEditor = getChild<LLExpandableTextBox>("description");
mMaturityRatingText = getChild<LLTextBox>("maturity_value");
mParcelOwner = getChild<LLTextBox>("owner_value");
@@ -456,13 +458,13 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data)
mSnapshotCtrl->setImageAssetID(parcel_data.snapshot_id);
}
- if(!parcel_data.name.empty())
+ if(!parcel_data.sim_name.empty())
{
- mParcelName->setText(parcel_data.name);
+ mRegionName->setText(parcel_data.sim_name);
}
else
{
- mParcelName->setText(LLStringUtil::null);
+ mRegionName->setText(LLStringUtil::null);
}
if(!parcel_data.desc.empty())
@@ -509,19 +511,22 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data)
region_z = llround(mPosRegion.mV[VZ]);
}
- std::string name = getString("not_available");
- if (!parcel_data.sim_name.empty())
+ if (!parcel_data.name.empty())
{
- name = llformat("%s (%d, %d, %d)",
- parcel_data.sim_name.c_str(), region_x, region_y, region_z);
- mRegionName->setText(name);
+ mParcelName->setText(llformat("%s (%d, %d, %d)",
+ parcel_data.name.c_str(), region_x, region_y, region_z));
+ }
+ else
+ {
+ mParcelName->setText(getString("not_available"));
}
if (mInfoType == CREATE_LANDMARK)
{
if (parcel_data.name.empty())
{
- mTitleEditor->setText(name);
+ mTitleEditor->setText(llformat("%s (%d, %d, %d)",
+ parcel_data.sim_name.c_str(), region_x, region_y, region_z));
}
else
{
@@ -610,6 +615,9 @@ void LLPanelPlaceInfo::displaySelectedParcelInfo(LLParcel* parcel,
parcel_data.name = parcel->getName();
parcel_data.sim_name = region->getName();
parcel_data.snapshot_id = parcel->getSnapshotID();
+ mPosRegion.setVec((F32)fmod(pos_global.mdV[VX], (F64)REGION_WIDTH_METERS),
+ (F32)fmod(pos_global.mdV[VY], (F64)REGION_WIDTH_METERS),
+ (F32)pos_global.mdV[VZ]);
parcel_data.global_x = pos_global.mdV[VX];
parcel_data.global_y = pos_global.mdV[VY];
parcel_data.global_z = pos_global.mdV[VZ];
@@ -986,18 +994,22 @@ void LLPanelPlaceInfo::populateFoldersList()
mFolderCombo->add(it->second, LLSD(it->first));
}
-void LLPanelPlaceInfo::updateYouAreHereBanner()
+//static
+void LLPanelPlaceInfo::updateYouAreHereBanner(void* userdata)
{
//YouAreHere Banner should be displayed only for selected places,
// If you want to display it for landmark or teleport history item, you should check by mParcelId
- bool is_you_are_here = false;
- if (mSelectedParcelID != S32(-1) && !mLastSelectedRegionID.isNull())
- {
- is_you_are_here = gAgent.getRegion()->getRegionID()== mLastSelectedRegionID &&
- mSelectedParcelID == LLViewerParcelMgr::getInstance()->getAgentParcel()->getLocalID();
- }
- mYouAreHerePanel->setVisible(is_you_are_here);
+ LLPanelPlaceInfo* self = static_cast<LLPanelPlaceInfo*>(userdata);
+ if(!self->getVisible())
+ return;
+
+ static F32 radius = gSavedSettings.getF32("YouAreHereDistance");
+
+ BOOL display_banner = self->mLastSelectedRegionID == gAgent.getRegion()->getRegionID() &&
+ LLAgentUI::checkAgentDistance(self->mPosRegion, radius);
+
+ self->mYouAreHerePanel->setVisible(display_banner);
}
void LLPanelPlaceInfo::onForSaleBannerClick()
@@ -1028,14 +1040,9 @@ void LLPanelPlaceInfo::onForSaleBannerClick()
}
-
-
-static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right)
-{
- return left.second < right.second;
-}
-static std::string getFullFolderName(const LLViewerInventoryCategory* cat)
+/*static*/
+std::string LLPanelPlaceInfo::getFullFolderName(const LLViewerInventoryCategory* cat)
{
std::string name = cat->getName();
LLUUID parent_id;
@@ -1057,6 +1064,11 @@ static std::string getFullFolderName(const LLViewerInventoryCategory* cat)
return name;
}
+static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right)
+{
+ return left.second < right.second;
+}
+
static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats)
{
LLUUID landmarks_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK);
diff --git a/indra/newview/llpanelplaceinfo.h b/indra/newview/llpanelplaceinfo.h
index 7b3a8f050b..07a2434d59 100644
--- a/indra/newview/llpanelplaceinfo.h
+++ b/indra/newview/llpanelplaceinfo.h
@@ -43,6 +43,7 @@
class LLButton;
class LLComboBox;
+class LLExpandableTextBox;
class LLInventoryItem;
class LLLineEditor;
class LLPanelPickEdit;
@@ -52,6 +53,7 @@ class LLTextBox;
class LLTextEditor;
class LLTextureCtrl;
class LLViewerRegion;
+class LLViewerInventoryCategory;
class LLPanelPlaceInfo : public LLPanel, LLRemoteParcelInfoObserver
{
@@ -131,11 +133,13 @@ public:
/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
/*virtual*/ void handleVisibilityChange (BOOL new_visibility);
+
+ static std::string getFullFolderName(const LLViewerInventoryCategory* cat);
private:
void populateFoldersList();
- void updateYouAreHereBanner();
+ static void updateYouAreHereBanner(void*);// added to gIdleCallbacks
void onForSaleBannerClick();
/**
@@ -161,7 +165,7 @@ private:
LLTextureCtrl* mSnapshotCtrl;
LLTextBox* mRegionName;
LLTextBox* mParcelName;
- LLTextEditor* mDescEditor;
+ LLExpandableTextBox*mDescEditor;
LLTextBox* mMaturityRatingText;
LLTextBox* mParcelOwner;
LLTextBox* mLastVisited;
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index 5ab823b6e5..b2e9110e96 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -351,7 +351,16 @@ void LLPanelPlaces::setItem(LLInventoryItem* item)
if (is_landmark_editable)
{
- mPlaceInfo->setLandmarkFolder(mItem->getParentUUID());
+ if(!mPlaceInfo->setLandmarkFolder(mItem->getParentUUID()) && !mItem->getParentUUID().isNull())
+ {
+ const LLViewerInventoryCategory* cat = gInventory.getCategory(mItem->getParentUUID());
+ if(cat)
+ {
+ std::string cat_fullname = LLPanelPlaceInfo::getFullFolderName(cat);
+ LLComboBox* folderList = mPlaceInfo->getChild<LLComboBox>("folder_combo");
+ folderList->add(cat_fullname, cat->getUUID(),ADD_TOP);
+ }
+ }
}
mPlaceInfo->displayItemInfo(mItem);
diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp
new file mode 100644
index 0000000000..cbff13a20f
--- /dev/null
+++ b/indra/newview/llpanelprimmediacontrols.cpp
@@ -0,0 +1,1103 @@
+/**
+ * @file llpanelprimmediacontrols.cpp
+ * @brief media controls popup panel
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ *
+ * Copyright (c) 2003-2007, 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://secondlife.com/developers/opensource/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://secondlife.com/developers/opensource/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"
+
+//LLPanelPrimMediaControls
+#include "llagent.h"
+#include "llparcel.h"
+#include "llpanel.h"
+#include "llselectmgr.h"
+#include "llmediaentry.h"
+#include "llrender.h"
+#include "lldrawable.h"
+#include "llviewerwindow.h"
+#include "lluictrlfactory.h"
+#include "llbutton.h"
+#include "llface.h"
+#include "llcombobox.h"
+#include "llslider.h"
+#include "llhudview.h"
+#include "lliconctrl.h"
+#include "lltoolpie.h"
+#include "llviewercamera.h"
+#include "llviewerobjectlist.h"
+#include "llpanelprimmediacontrols.h"
+#include "llpluginclassmedia.h"
+#include "llprogressbar.h"
+#include "llviewercontrol.h"
+#include "llviewerparcelmgr.h"
+#include "llviewermedia.h"
+#include "llviewermediafocus.h"
+#include "llvovolume.h"
+#include "llweb.h"
+#include "llwindow.h"
+
+glh::matrix4f glh_get_current_modelview();
+glh::matrix4f glh_get_current_projection();
+
+const F32 ZOOM_NEAR_PADDING = 1.0f;
+const F32 ZOOM_MEDIUM_PADDING = 1.15f;
+const F32 ZOOM_FAR_PADDING = 1.5f;
+
+// Warning: make sure these two match!
+const LLPanelPrimMediaControls::EZoomLevel LLPanelPrimMediaControls::kZoomLevels[] = { ZOOM_NONE, ZOOM_MEDIUM };
+const int LLPanelPrimMediaControls::kNumZoomLevels = 2;
+
+//
+// LLPanelPrimMediaControls
+//
+
+LLPanelPrimMediaControls::LLPanelPrimMediaControls() :
+ mAlpha(1.f),
+ mCurrentURL(""),
+ mPreviousURL(""),
+ mPauseFadeout(false),
+ mUpdateSlider(true),
+ mClearFaceOnFade(false),
+ mCurrentRate(0.0),
+ mMovieDuration(0.0),
+ mUpdatePercent(0)
+{
+ mCommitCallbackRegistrar.add("MediaCtrl.Close", boost::bind(&LLPanelPrimMediaControls::onClickClose, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.Back", boost::bind(&LLPanelPrimMediaControls::onClickBack, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.Forward", boost::bind(&LLPanelPrimMediaControls::onClickForward, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.Home", boost::bind(&LLPanelPrimMediaControls::onClickHome, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.Stop", boost::bind(&LLPanelPrimMediaControls::onClickStop, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.Reload", boost::bind(&LLPanelPrimMediaControls::onClickReload, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.Play", boost::bind(&LLPanelPrimMediaControls::onClickPlay, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.Pause", boost::bind(&LLPanelPrimMediaControls::onClickPause, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.Open", boost::bind(&LLPanelPrimMediaControls::onClickOpen, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.Zoom", boost::bind(&LLPanelPrimMediaControls::onClickZoom, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.CommitURL", boost::bind(&LLPanelPrimMediaControls::onCommitURL, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.JumpProgress", boost::bind(&LLPanelPrimMediaControls::onCommitSlider, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.CommitVolumeUp", boost::bind(&LLPanelPrimMediaControls::onCommitVolumeUp, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.CommitVolumeDown", boost::bind(&LLPanelPrimMediaControls::onCommitVolumeDown, this));
+ mCommitCallbackRegistrar.add("MediaCtrl.ToggleMute", boost::bind(&LLPanelPrimMediaControls::onToggleMute, this));
+
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_prim_media_controls.xml");
+ mInactivityTimer.reset();
+ mFadeTimer.stop();
+ mCurrentZoom = ZOOM_NONE;
+ mScrollState = SCROLL_NONE;
+
+ mPanelHandle.bind(this);
+}
+LLPanelPrimMediaControls::~LLPanelPrimMediaControls()
+{
+}
+
+BOOL LLPanelPrimMediaControls::postBuild()
+{
+ LLButton* scroll_up_ctrl = getChild<LLButton>("scrollup");
+ scroll_up_ctrl->setClickedCallback(onScrollUp, this);
+ scroll_up_ctrl->setHeldDownCallback(onScrollUpHeld, this);
+ scroll_up_ctrl->setMouseUpCallback(onScrollStop, this);
+ LLButton* scroll_left_ctrl = getChild<LLButton>("scrollleft");
+ scroll_left_ctrl->setClickedCallback(onScrollLeft, this);
+ scroll_left_ctrl->setHeldDownCallback(onScrollLeftHeld, this);
+ scroll_left_ctrl->setMouseUpCallback(onScrollStop, this);
+ LLButton* scroll_right_ctrl = getChild<LLButton>("scrollright");
+ scroll_right_ctrl->setClickedCallback(onScrollRight, this);
+ scroll_right_ctrl->setHeldDownCallback(onScrollLeftHeld, this);
+ scroll_right_ctrl->setMouseUpCallback(onScrollStop, this);
+ LLButton* scroll_down_ctrl = getChild<LLButton>("scrolldown");
+ scroll_down_ctrl->setClickedCallback(onScrollDown, this);
+ scroll_down_ctrl->setHeldDownCallback(onScrollDownHeld, this);
+ scroll_down_ctrl->setMouseUpCallback(onScrollStop, this);
+
+ LLUICtrl* media_address = getChild<LLUICtrl>("media_address");
+ media_address->setFocusReceivedCallback(boost::bind(&LLPanelPrimMediaControls::onInputURL, _1, this ));
+ mInactiveTimeout = gSavedSettings.getF32("MediaControlTimeout");
+ mControlFadeTime = gSavedSettings.getF32("MediaControlFadeTime");
+
+ mCurrentZoom = ZOOM_NONE;
+ // clicks on HUD buttons do not remove keyboard focus from media
+ setIsChrome(TRUE);
+ return TRUE;
+}
+
+void LLPanelPrimMediaControls::setMediaFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal)
+{
+ if (media_impl.notNull() && objectp.notNull())
+ {
+ mTargetImplID = media_impl->getMediaTextureID();
+ mTargetObjectID = objectp->getID();
+ mTargetObjectFace = face;
+ mTargetObjectNormal = pick_normal;
+ mClearFaceOnFade = false;
+ }
+ else
+ {
+ // This happens on a timer now.
+// mTargetImplID = LLUUID::null;
+// mTargetObjectID = LLUUID::null;
+// mTargetObjectFace = 0;
+ mClearFaceOnFade = true;
+ }
+
+ updateShape();
+}
+
+void LLPanelPrimMediaControls::focusOnTarget()
+{
+ // Sets the media focus to the current target of the LLPanelPrimMediaControls.
+ // This is how we transition from hover to focus when the user clicks on a control.
+ LLViewerMediaImpl* media_impl = getTargetMediaImpl();
+ if(media_impl)
+ {
+ if(!media_impl->hasFocus())
+ {
+ // The current target doesn't have media focus -- focus on it.
+ LLViewerObject* objectp = getTargetObject();
+ LLViewerMediaFocus::getInstance()->setFocusFace(objectp, mTargetObjectFace, media_impl, mTargetObjectNormal);
+ }
+ }
+}
+
+LLViewerMediaImpl* LLPanelPrimMediaControls::getTargetMediaImpl()
+{
+ return LLViewerMedia::getMediaImplFromTextureID(mTargetImplID);
+}
+
+LLViewerObject* LLPanelPrimMediaControls::getTargetObject()
+{
+ return gObjectList.findObject(mTargetObjectID);
+}
+
+LLPluginClassMedia* LLPanelPrimMediaControls::getTargetMediaPlugin()
+{
+ LLViewerMediaImpl* impl = getTargetMediaImpl();
+ if(impl && impl->hasMedia())
+ {
+ return impl->getMediaPlugin();
+ }
+
+ return NULL;
+}
+
+void LLPanelPrimMediaControls::updateShape()
+{
+ const S32 MIN_HUD_WIDTH=400;
+ const S32 MIN_HUD_HEIGHT=120;
+
+ LLViewerMediaImpl* media_impl = getTargetMediaImpl();
+ LLViewerObject* objectp = getTargetObject();
+
+ if(!media_impl)
+ {
+ setVisible(FALSE);
+ return;
+ }
+
+ LLPluginClassMedia* media_plugin = NULL;
+ if(media_impl->hasMedia())
+ {
+ media_plugin = media_impl->getMediaPlugin();
+ }
+
+ LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+
+ bool can_navigate = parcel->getMediaAllowNavigate();
+ bool enabled = false;
+ bool has_focus = media_impl->hasFocus();
+ setVisible(enabled);
+
+ if (objectp)
+ {
+ bool mini_controls = false;
+ LLMediaEntry *media_data = objectp->getTE(mTargetObjectFace)->getMediaData();
+ if (media_data && NULL != dynamic_cast<LLVOVolume*>(objectp))
+ {
+ // Don't show the media HUD if we do not have permissions
+ enabled = dynamic_cast<LLVOVolume*>(objectp)->hasMediaPermission(media_data, LLVOVolume::MEDIA_PERM_CONTROL);
+ mini_controls = (LLMediaEntry::MINI == media_data->getControls());
+ }
+
+ //
+ // Set the state of the buttons
+ //
+ LLUICtrl* back_ctrl = getChild<LLUICtrl>("back");
+ LLUICtrl* fwd_ctrl = getChild<LLUICtrl>("fwd");
+ LLUICtrl* reload_ctrl = getChild<LLUICtrl>("reload");
+ LLUICtrl* play_ctrl = getChild<LLUICtrl>("play");
+ LLUICtrl* pause_ctrl = getChild<LLUICtrl>("pause");
+ LLUICtrl* stop_ctrl = getChild<LLUICtrl>("stop");
+ LLUICtrl* media_stop_ctrl = getChild<LLUICtrl>("media_stop");
+ LLUICtrl* home_ctrl = getChild<LLUICtrl>("home");
+ LLUICtrl* close_ctrl = getChild<LLUICtrl>("close");
+ LLUICtrl* open_ctrl = getChild<LLUICtrl>("new_window");
+ LLUICtrl* zoom_ctrl = getChild<LLUICtrl>("zoom_frame");
+ LLPanel* media_loading_panel = getChild<LLPanel>("media_progress_indicator");
+ LLUICtrl* media_address_ctrl = getChild<LLUICtrl>("media_address");
+ LLUICtrl* media_play_slider_ctrl = getChild<LLUICtrl>("media_play_position");
+ LLUICtrl* volume_ctrl = getChild<LLUICtrl>("media_volume");
+ LLButton* volume_btn = getChild<LLButton>("media_volume_button");
+ LLUICtrl* volume_up_ctrl = getChild<LLUICtrl>("volume_up");
+ LLUICtrl* volume_down_ctrl = getChild<LLUICtrl>("volume_down");
+ LLIconCtrl* whitelist_icon = getChild<LLIconCtrl>("media_whitelist_flag");
+ LLIconCtrl* secure_lock_icon = getChild<LLIconCtrl>("media_secure_lock_flag");
+
+ LLUICtrl* media_panel_scroll = getChild<LLUICtrl>("media_panel_scroll");
+ LLUICtrl* scroll_up_ctrl = getChild<LLUICtrl>("scrollup");
+ LLUICtrl* scroll_left_ctrl = getChild<LLUICtrl>("scrollleft");
+ LLUICtrl* scroll_right_ctrl = getChild<LLUICtrl>("scrollright");
+ LLUICtrl* scroll_down_ctrl = getChild<LLUICtrl>("scrolldown");
+
+ // XXX RSP: TODO: FIXME: clean this up so that it is clearer what mode we are in,
+ // and that only the proper controls get made visible/enabled according to that mode.
+ back_ctrl->setVisible(has_focus);
+ fwd_ctrl->setVisible(has_focus);
+ reload_ctrl->setVisible(has_focus);
+ stop_ctrl->setVisible(false);
+ home_ctrl->setVisible(has_focus);
+ close_ctrl->setVisible(has_focus);
+ open_ctrl->setVisible(true);
+ media_address_ctrl->setVisible(has_focus && !mini_controls);
+ media_play_slider_ctrl->setVisible(has_focus && !mini_controls);
+ volume_ctrl->setVisible(false);
+ volume_up_ctrl->setVisible(false);
+ volume_down_ctrl->setVisible(false);
+
+ whitelist_icon->setVisible(!mini_controls && (media_data)?media_data->getWhiteListEnable():false);
+ // Disable zoom if HUD
+ zoom_ctrl->setEnabled(!objectp->isHUDAttachment());
+ secure_lock_icon->setVisible(false);
+ mCurrentURL = media_impl->getMediaURL();
+
+ back_ctrl->setEnabled((media_impl != NULL) && media_impl->canNavigateBack() && can_navigate);
+ fwd_ctrl->setEnabled((media_impl != NULL) && media_impl->canNavigateForward() && can_navigate);
+ stop_ctrl->setEnabled(has_focus && can_navigate);
+ home_ctrl->setEnabled(has_focus && can_navigate);
+ LLPluginClassMediaOwner::EMediaStatus result = ((media_impl != NULL) && media_impl->hasMedia()) ? media_plugin->getStatus() : LLPluginClassMediaOwner::MEDIA_NONE;
+
+ if(media_plugin && media_plugin->pluginSupportsMediaTime())
+ {
+ reload_ctrl->setEnabled(FALSE);
+ reload_ctrl->setVisible(FALSE);
+ media_stop_ctrl->setVisible(has_focus);
+ home_ctrl->setVisible(FALSE);
+ back_ctrl->setEnabled(has_focus);
+ fwd_ctrl->setEnabled(has_focus);
+ media_address_ctrl->setVisible(false);
+ media_address_ctrl->setEnabled(false);
+ media_play_slider_ctrl->setVisible(!mini_controls);
+ media_play_slider_ctrl->setEnabled(!mini_controls);
+
+ volume_ctrl->setVisible(has_focus);
+ volume_up_ctrl->setVisible(has_focus);
+ volume_down_ctrl->setVisible(has_focus);
+ volume_ctrl->setEnabled(has_focus);
+
+ whitelist_icon->setVisible(false);
+ secure_lock_icon->setVisible(false);
+ scroll_up_ctrl->setVisible(false);
+ scroll_left_ctrl->setVisible(false);
+ scroll_right_ctrl->setVisible(false);
+ scroll_down_ctrl->setVisible(false);
+ media_panel_scroll->setVisible(false);
+
+ F32 volume = media_impl->getVolume();
+ // movie's url changed
+ if(mCurrentURL!=mPreviousURL)
+ {
+ mMovieDuration = media_plugin->getDuration();
+ mPreviousURL = mCurrentURL;
+ }
+
+ if(mMovieDuration == 0)
+ {
+ mMovieDuration = media_plugin->getDuration();
+ media_play_slider_ctrl->setValue(0);
+ media_play_slider_ctrl->setEnabled(false);
+ }
+ // TODO: What if it's not fully loaded
+
+ if(mUpdateSlider && mMovieDuration!= 0)
+ {
+ F64 current_time = media_plugin->getCurrentTime();
+ F32 percent = current_time / mMovieDuration;
+ media_play_slider_ctrl->setValue(percent);
+ media_play_slider_ctrl->setEnabled(true);
+ }
+
+ // video vloume
+ if(volume <= 0.0)
+ {
+ volume_up_ctrl->setEnabled(TRUE);
+ volume_down_ctrl->setEnabled(FALSE);
+ media_impl->setVolume(0.0);
+ volume_btn->setToggleState(true);
+ }
+ else if (volume >= 1.0)
+ {
+ volume_up_ctrl->setEnabled(FALSE);
+ volume_down_ctrl->setEnabled(TRUE);
+ media_impl->setVolume(1.0);
+ volume_btn->setToggleState(false);
+ }
+ else
+ {
+ volume_up_ctrl->setEnabled(TRUE);
+ volume_down_ctrl->setEnabled(TRUE);
+ }
+
+ switch(result)
+ {
+ case LLPluginClassMediaOwner::MEDIA_PLAYING:
+ play_ctrl->setEnabled(FALSE);
+ play_ctrl->setVisible(FALSE);
+ pause_ctrl->setEnabled(TRUE);
+ pause_ctrl->setVisible(has_focus);
+ media_stop_ctrl->setEnabled(TRUE);
+
+ break;
+ case LLPluginClassMediaOwner::MEDIA_PAUSED:
+ default:
+ pause_ctrl->setEnabled(FALSE);
+ pause_ctrl->setVisible(FALSE);
+ play_ctrl->setEnabled(TRUE);
+ play_ctrl->setVisible(has_focus);
+ media_stop_ctrl->setEnabled(FALSE);
+ break;
+ }
+ }
+ else // web based
+ {
+ if(media_plugin)
+ {
+ mCurrentURL = media_plugin->getLocation();
+ }
+ else
+ {
+ mCurrentURL.clear();
+ }
+
+ play_ctrl->setVisible(FALSE);
+ pause_ctrl->setVisible(FALSE);
+ media_stop_ctrl->setVisible(FALSE);
+ media_address_ctrl->setVisible(has_focus && !mini_controls);
+ media_address_ctrl->setEnabled(has_focus && !mini_controls);
+ media_play_slider_ctrl->setVisible(FALSE);
+ media_play_slider_ctrl->setEnabled(FALSE);
+
+ volume_ctrl->setVisible(FALSE);
+ volume_up_ctrl->setVisible(FALSE);
+ volume_down_ctrl->setVisible(FALSE);
+ volume_ctrl->setEnabled(FALSE);
+ volume_up_ctrl->setEnabled(FALSE);
+ volume_down_ctrl->setEnabled(FALSE);
+
+ scroll_up_ctrl->setVisible(has_focus);
+ scroll_left_ctrl->setVisible(has_focus);
+ scroll_right_ctrl->setVisible(has_focus);
+ scroll_down_ctrl->setVisible(has_focus);
+ media_panel_scroll->setVisible(has_focus);
+ // TODO: get the secure lock bool from media plug in
+ std::string prefix = std::string("https://");
+ std::string test_prefix = mCurrentURL.substr(0, prefix.length());
+ LLStringUtil::toLower(test_prefix);
+ if(test_prefix == prefix)
+ {
+ secure_lock_icon->setVisible(has_focus);
+ }
+
+ if(mCurrentURL!=mPreviousURL)
+ {
+ setCurrentURL();
+ mPreviousURL = mCurrentURL;
+ }
+
+ if(result == LLPluginClassMediaOwner::MEDIA_LOADING)
+ {
+ reload_ctrl->setEnabled(FALSE);
+ reload_ctrl->setVisible(FALSE);
+ stop_ctrl->setEnabled(TRUE);
+ stop_ctrl->setVisible(has_focus);
+ }
+ else
+ {
+ reload_ctrl->setEnabled(TRUE);
+ reload_ctrl->setVisible(has_focus);
+ stop_ctrl->setEnabled(FALSE);
+ stop_ctrl->setVisible(FALSE);
+ }
+ }
+
+
+ if(media_plugin)
+ {
+ //
+ // Handle progress bar
+ //
+ mUpdatePercent = media_plugin->getProgressPercent();
+ if(mUpdatePercent<100.0f)
+ {
+ media_loading_panel->setVisible(true);
+ getChild<LLProgressBar>("media_progress_bar")->setPercent(mUpdatePercent);
+ gFocusMgr.setTopCtrl(media_loading_panel);
+ }
+ else
+ {
+ media_loading_panel->setVisible(false);
+ gFocusMgr.setTopCtrl(NULL);
+ }
+ }
+
+ if(media_plugin)
+ {
+ //
+ // Handle Scrolling
+ //
+ switch (mScrollState)
+ {
+ case SCROLL_UP:
+ media_plugin->scrollEvent(0, -1, MASK_NONE);
+ break;
+ case SCROLL_DOWN:
+ media_plugin->scrollEvent(0, 1, MASK_NONE);
+ break;
+ case SCROLL_LEFT:
+ media_impl->handleKeyHere(KEY_LEFT, MASK_NONE);
+ break;
+ case SCROLL_RIGHT:
+ media_impl->handleKeyHere(KEY_RIGHT, MASK_NONE);
+ break;
+ case SCROLL_NONE:
+ default:
+ break;
+ }
+ }
+
+ setVisible(enabled);
+
+ //
+ // Calculate position and shape of the controls
+ //
+ glh::matrix4f mat = glh_get_current_projection()*glh_get_current_modelview();
+ std::vector<LLVector3>::iterator vert_it;
+ std::vector<LLVector3>::iterator vert_end;
+ std::vector<LLVector3> vect_face;
+
+ LLVolume* volume = objectp->getVolume();
+
+ if (volume)
+ {
+ const LLVolumeFace& vf = volume->getVolumeFace(mTargetObjectFace);
+
+ const LLVector3* ext = vf.mExtents;
+
+ LLVector3 center = (ext[0]+ext[1])*0.5f;
+ LLVector3 size = (ext[1]-ext[0])*0.5f;
+ LLVector3 vert[] =
+ {
+ center + size.scaledVec(LLVector3(1,1,1)),
+ center + size.scaledVec(LLVector3(-1,1,1)),
+ center + size.scaledVec(LLVector3(1,-1,1)),
+ center + size.scaledVec(LLVector3(-1,-1,1)),
+ center + size.scaledVec(LLVector3(1,1,-1)),
+ center + size.scaledVec(LLVector3(-1,1,-1)),
+ center + size.scaledVec(LLVector3(1,-1,-1)),
+ center + size.scaledVec(LLVector3(-1,-1,-1)),
+ };
+
+ LLVOVolume* vo = (LLVOVolume*) objectp;
+
+ for (U32 i = 0; i < 8; i++)
+ {
+ vect_face.push_back(vo->volumePositionToAgent(vert[i]));
+ }
+ }
+ vert_it = vect_face.begin();
+ vert_end = vect_face.end();
+
+ LLVector3 min = LLVector3(1,1,1);
+ LLVector3 max = LLVector3(-1,-1,-1);
+ for(; vert_it != vert_end; ++vert_it)
+ {
+ // project silhouette vertices into screen space
+ glh::vec3f screen_vert = glh::vec3f(vert_it->mV);
+ mat.mult_matrix_vec(screen_vert);
+
+ // add to screenspace bounding box
+ update_min_max(min, max, LLVector3(screen_vert.v));
+ }
+
+ LLCoordGL screen_min;
+ screen_min.mX = llround((F32)gViewerWindow->getWorldViewWidth() * (min.mV[VX] + 1.f) * 0.5f);
+ screen_min.mY = llround((F32)gViewerWindow->getWorldViewHeight() * (min.mV[VY] + 1.f) * 0.5f);
+
+ LLCoordGL screen_max;
+ screen_max.mX = llround((F32)gViewerWindow->getWorldViewWidth() * (max.mV[VX] + 1.f) * 0.5f);
+ screen_max.mY = llround((F32)gViewerWindow->getWorldViewHeight() * (max.mV[VY] + 1.f) * 0.5f);
+
+ // grow panel so that screenspace bounding box fits inside "media_region" element of HUD
+ LLRect media_controls_rect;
+ getParent()->screenRectToLocal(LLRect(screen_min.mX, screen_max.mY, screen_max.mX, screen_min.mY), &media_controls_rect);
+ LLView* media_region = getChild<LLView>("media_region");
+ media_controls_rect.mLeft -= media_region->getRect().mLeft;
+ media_controls_rect.mBottom -= media_region->getRect().mBottom;
+ media_controls_rect.mTop += getRect().getHeight() - media_region->getRect().mTop;
+ media_controls_rect.mRight += getRect().getWidth() - media_region->getRect().mRight;
+
+ LLRect old_hud_rect = media_controls_rect;
+ // keep all parts of HUD on-screen
+ media_controls_rect.intersectWith(getParent()->getLocalRect());
+
+ // clamp to minimum size, keeping centered
+ media_controls_rect.setCenterAndSize(media_controls_rect.getCenterX(), media_controls_rect.getCenterY(),
+ llmax(MIN_HUD_WIDTH, media_controls_rect.getWidth()), llmax(MIN_HUD_HEIGHT, media_controls_rect.getHeight()));
+
+ setShape(media_controls_rect, true);
+
+ // Test mouse position to see if the cursor is stationary
+ LLCoordWindow cursor_pos_window;
+ getWindow()->getCursorPosition(&cursor_pos_window);
+
+ // If last pos is not equal to current pos, the mouse has moved
+ // We need to reset the timer, and make sure the panel is visible
+ if(cursor_pos_window.mX != mLastCursorPos.mX ||
+ cursor_pos_window.mY != mLastCursorPos.mY ||
+ mScrollState != SCROLL_NONE)
+ {
+ mInactivityTimer.start();
+ mLastCursorPos = cursor_pos_window;
+ }
+
+ if(isMouseOver())
+ {
+ // Never fade the controls if the mouse is over them.
+ mFadeTimer.stop();
+ }
+ else if(!mClearFaceOnFade && (mInactivityTimer.getElapsedTimeF32() < mInactiveTimeout))
+ {
+ // Mouse is over the object, but has not been stationary for long enough to fade the UI
+ mFadeTimer.stop();
+ }
+ else if(! mFadeTimer.getStarted() )
+ {
+ // we need to start fading the UI (and we have not already started)
+ mFadeTimer.reset();
+ mFadeTimer.start();
+ }
+ else
+ {
+ // I don't think this is correct anymore. This is done in draw() after the fade has completed.
+// setVisible(FALSE);
+ }
+ }
+}
+
+/*virtual*/
+void LLPanelPrimMediaControls::draw()
+{
+ F32 alpha = 1.f;
+ if(mFadeTimer.getStarted())
+ {
+ F32 time = mFadeTimer.getElapsedTimeF32();
+ alpha = llmax(lerp(1.0, 0.0, time / mControlFadeTime), 0.0f);
+
+ if(mFadeTimer.getElapsedTimeF32() >= mControlFadeTime)
+ {
+ setVisible(FALSE);
+ if(mClearFaceOnFade)
+ {
+ mClearFaceOnFade = false;
+ mTargetImplID = LLUUID::null;
+ mTargetObjectID = LLUUID::null;
+ mTargetObjectFace = 0;
+ }
+ }
+ }
+
+ {
+ LLViewDrawContext context(alpha);
+ LLPanel::draw();
+ }
+}
+
+BOOL LLPanelPrimMediaControls::handleScrollWheel(S32 x, S32 y, S32 clicks)
+{
+ mInactivityTimer.start();
+ return LLViewerMediaFocus::getInstance()->handleScrollWheel(x, y, clicks);
+}
+
+BOOL LLPanelPrimMediaControls::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ mInactivityTimer.start();
+ return LLPanel::handleMouseDown(x, y, mask);
+}
+
+BOOL LLPanelPrimMediaControls::handleMouseUp(S32 x, S32 y, MASK mask)
+{
+ mInactivityTimer.start();
+ return LLPanel::handleMouseUp(x, y, mask);
+}
+
+BOOL LLPanelPrimMediaControls::handleKeyHere( KEY key, MASK mask )
+{
+ mInactivityTimer.start();
+ return LLPanel::handleKeyHere(key, mask);
+}
+
+bool LLPanelPrimMediaControls::isMouseOver()
+{
+ bool result = false;
+
+ if( getVisible() )
+ {
+ LLCoordWindow cursor_pos_window;
+ LLCoordScreen cursor_pos_screen;
+ LLCoordGL cursor_pos_gl;
+ S32 x, y;
+ getWindow()->getCursorPosition(&cursor_pos_window);
+ getWindow()->convertCoords(cursor_pos_window, &cursor_pos_gl);
+
+ LLPanel* controls_panel = NULL;
+ controls_panel = getChild<LLPanel>("media_hover_controls");
+ if(controls_panel && !controls_panel->getVisible())
+ {
+ // The hover controls aren't visible -- use the focused controls instead.
+ controls_panel = getChild<LLPanel>("media_focused_controls");
+ }
+
+ if(controls_panel && controls_panel->getVisible())
+ {
+ controls_panel->screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, &x, &y);
+
+ LLView *hit_child = controls_panel->childFromPoint(x, y);
+ if(hit_child)
+ {
+ // This was useful for debugging both coordinate translation and view hieararchy problems...
+// llinfos << "mouse coords: " << x << ", " << y << " hit child " << hit_child->getName() << llendl;
+ result = true;
+ }
+ }
+ }
+
+ return result;
+}
+
+
+void LLPanelPrimMediaControls::onClickClose()
+{
+ close();
+}
+
+void LLPanelPrimMediaControls::close()
+{
+ LLViewerMediaFocus::getInstance()->clearFocus();
+ resetZoomLevel();
+ setVisible(FALSE);
+}
+
+
+void LLPanelPrimMediaControls::onClickBack()
+{
+ focusOnTarget();
+
+ LLViewerMediaImpl* impl =getTargetMediaImpl();
+
+ if (impl)
+ {
+ impl->navigateBack();
+ }
+}
+
+void LLPanelPrimMediaControls::onClickForward()
+{
+ focusOnTarget();
+
+ LLViewerMediaImpl* impl = getTargetMediaImpl();
+
+ if (impl)
+ {
+ impl->navigateForward();
+ }
+}
+
+void LLPanelPrimMediaControls::onClickHome()
+{
+ focusOnTarget();
+
+ LLViewerMediaImpl* impl = getTargetMediaImpl();
+
+ if(impl)
+ {
+ impl->navigateHome();
+ }
+}
+
+void LLPanelPrimMediaControls::onClickOpen()
+{
+ LLViewerMediaImpl* impl =getTargetMediaImpl();
+ if(impl)
+ {
+ if(impl->getMediaPlugin())
+ {
+ if(impl->getMediaPlugin()->getLocation().empty())
+ {
+ LLWeb::loadURL(impl->getMediaURL());
+ }
+ else
+ {
+ LLWeb::loadURL( impl->getMediaPlugin()->getLocation());
+ }
+ }
+ }
+}
+
+void LLPanelPrimMediaControls::onClickReload()
+{
+ focusOnTarget();
+
+ //LLViewerMedia::navigateHome();
+ LLViewerMediaImpl* impl = getTargetMediaImpl();
+
+ if(impl)
+ {
+ impl->navigateReload();
+ }
+}
+
+void LLPanelPrimMediaControls::onClickPlay()
+{
+ focusOnTarget();
+
+ LLViewerMediaImpl* impl = getTargetMediaImpl();
+
+ if(impl)
+ {
+ impl->play();
+ }
+}
+
+void LLPanelPrimMediaControls::onClickPause()
+{
+ focusOnTarget();
+
+ LLViewerMediaImpl* impl = getTargetMediaImpl();
+
+ if(impl)
+ {
+ impl->pause();
+ }
+}
+
+void LLPanelPrimMediaControls::onClickStop()
+{
+ focusOnTarget();
+
+ LLViewerMediaImpl* impl = getTargetMediaImpl();
+
+ if(impl)
+ {
+ impl->stop();
+ }
+}
+
+void LLPanelPrimMediaControls::onClickZoom()
+{
+ focusOnTarget();
+
+ nextZoomLevel();
+}
+void LLPanelPrimMediaControls::nextZoomLevel()
+{
+ int index = 0;
+ while (index < kNumZoomLevels)
+ {
+ if (kZoomLevels[index] == mCurrentZoom)
+ {
+ index++;
+ break;
+ }
+ index++;
+ }
+ mCurrentZoom = kZoomLevels[index % kNumZoomLevels];
+ updateZoom();
+}
+
+void LLPanelPrimMediaControls::resetZoomLevel()
+{
+ if(mCurrentZoom != ZOOM_NONE)
+ {
+ mCurrentZoom = ZOOM_NONE;
+ updateZoom();
+ }
+}
+
+void LLPanelPrimMediaControls::updateZoom()
+{
+ F32 zoom_padding = 0.0f;
+ switch (mCurrentZoom)
+ {
+ case ZOOM_NONE:
+ {
+ gAgent.setFocusOnAvatar(TRUE, ANIMATE);
+ break;
+ }
+ case ZOOM_FAR:
+ {
+ zoom_padding = ZOOM_FAR_PADDING;
+ break;
+ }
+ case ZOOM_MEDIUM:
+ {
+ zoom_padding = ZOOM_MEDIUM_PADDING;
+ break;
+ }
+ case ZOOM_NEAR:
+ {
+ zoom_padding = ZOOM_NEAR_PADDING;
+ break;
+ }
+ default:
+ {
+ gAgent.setFocusOnAvatar(TRUE, ANIMATE);
+ break;
+ }
+ }
+
+ if (zoom_padding > 0.0f)
+ LLViewerMediaFocus::setCameraZoom(getTargetObject(), mTargetObjectNormal, zoom_padding);
+}
+void LLPanelPrimMediaControls::onScrollUp(void* user_data)
+{
+ LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+ this_panel->focusOnTarget();
+
+ LLPluginClassMedia* plugin = this_panel->getTargetMediaPlugin();
+
+ if(plugin)
+ {
+ plugin->scrollEvent(0, -1, MASK_NONE);
+ }
+}
+void LLPanelPrimMediaControls::onScrollUpHeld(void* user_data)
+{
+ LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+ this_panel->mScrollState = SCROLL_UP;
+}
+void LLPanelPrimMediaControls::onScrollRight(void* user_data)
+{
+ LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+ this_panel->focusOnTarget();
+
+ LLViewerMediaImpl* impl = this_panel->getTargetMediaImpl();
+
+ if(impl)
+ {
+ impl->handleKeyHere(KEY_RIGHT, MASK_NONE);
+ }
+}
+void LLPanelPrimMediaControls::onScrollRightHeld(void* user_data)
+{
+ LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+ this_panel->mScrollState = SCROLL_RIGHT;
+}
+
+void LLPanelPrimMediaControls::onScrollLeft(void* user_data)
+{
+ LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+ this_panel->focusOnTarget();
+
+ LLViewerMediaImpl* impl = this_panel->getTargetMediaImpl();
+
+ if(impl)
+ {
+ impl->handleKeyHere(KEY_LEFT, MASK_NONE);
+ }
+}
+void LLPanelPrimMediaControls::onScrollLeftHeld(void* user_data)
+{
+ LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+ this_panel->mScrollState = SCROLL_LEFT;
+}
+
+void LLPanelPrimMediaControls::onScrollDown(void* user_data)
+{
+ LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+ this_panel->focusOnTarget();
+
+ LLPluginClassMedia* plugin = this_panel->getTargetMediaPlugin();
+
+ if(plugin)
+ {
+ plugin->scrollEvent(0, 1, MASK_NONE);
+ }
+}
+void LLPanelPrimMediaControls::onScrollDownHeld(void* user_data)
+{
+ LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+ this_panel->mScrollState = SCROLL_DOWN;
+}
+
+void LLPanelPrimMediaControls::onScrollStop(void* user_data)
+{
+ LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (user_data);
+ this_panel->mScrollState = SCROLL_NONE;
+}
+
+void LLPanelPrimMediaControls::onCommitURL()
+{
+ focusOnTarget();
+
+ LLUICtrl *media_address_ctrl = getChild<LLUICtrl>("media_address_url");
+ std::string url = media_address_ctrl->getValue().asString();
+ if(getTargetMediaImpl() && !url.empty())
+ {
+ getTargetMediaImpl()->navigateTo( url, "", true);
+
+ // Make sure keyboard focus is set to the media focus object.
+ gFocusMgr.setKeyboardFocus(LLViewerMediaFocus::getInstance());
+
+ }
+ mPauseFadeout = false;
+ mFadeTimer.start();
+}
+
+
+void LLPanelPrimMediaControls::onInputURL(LLFocusableElement* caller, void *userdata)
+{
+
+ LLPanelPrimMediaControls* this_panel = static_cast<LLPanelPrimMediaControls*> (userdata);
+ this_panel->focusOnTarget();
+
+ this_panel->mPauseFadeout = true;
+ this_panel->mFadeTimer.stop();
+ this_panel->mFadeTimer.reset();
+
+}
+
+void LLPanelPrimMediaControls::setCurrentURL()
+{
+#ifdef USE_COMBO_BOX_FOR_MEDIA_URL
+ LLComboBox* media_address_combo = getChild<LLComboBox>("media_address_combo");
+ // redirects will navigate momentarily to about:blank, don't add to history
+ if (media_address_combo && mCurrentURL != "about:blank")
+ {
+ media_address_combo->remove(mCurrentURL);
+ media_address_combo->add(mCurrentURL, ADD_SORTED);
+ media_address_combo->selectByValue(mCurrentURL);
+ }
+#else // USE_COMBO_BOX_FOR_MEDIA_URL
+ LLLineEditor* media_address_url = getChild<LLLineEditor>("media_address_url");
+ if (media_address_url && mCurrentURL != "about:blank")
+ {
+ media_address_url->setValue(mCurrentURL);
+ }
+#endif // USE_COMBO_BOX_FOR_MEDIA_URL
+}
+
+void LLPanelPrimMediaControls::onCommitSlider()
+{
+ focusOnTarget();
+
+ LLSlider* media_play_slider_ctrl = getChild<LLSlider>("media_play_slider");
+ LLViewerMediaImpl* media_impl = getTargetMediaImpl();
+ if (media_impl)
+ {
+ // get slider value
+ F64 slider_value = media_play_slider_ctrl->getValue().asReal();
+ if(slider_value <= 0.0)
+ {
+ media_impl->stop();
+ }
+ else
+ {
+ media_impl->seek(slider_value*mMovieDuration);
+ //mUpdateSlider= false;
+ }
+ }
+}
+
+void LLPanelPrimMediaControls::onCommitVolumeUp()
+{
+ focusOnTarget();
+
+ LLViewerMediaImpl* media_impl = getTargetMediaImpl();
+ if (media_impl)
+ {
+ F32 volume = media_impl->getVolume();
+
+ volume += 0.1f;
+ if(volume >= 1.0f)
+ {
+ volume = 1.0f;
+ }
+
+ media_impl->setVolume(volume);
+ getChild<LLButton>("media_volume")->setToggleState(false);
+ }
+}
+
+void LLPanelPrimMediaControls::onCommitVolumeDown()
+{
+ focusOnTarget();
+
+ LLViewerMediaImpl* media_impl = getTargetMediaImpl();
+ if (media_impl)
+ {
+ F32 volume = media_impl->getVolume();
+
+ volume -= 0.1f;
+ if(volume <= 0.0f)
+ {
+ volume = 0.0f;
+ }
+
+ media_impl->setVolume(volume);
+ getChild<LLButton>("media_volume")->setToggleState(false);
+ }
+}
+
+
+void LLPanelPrimMediaControls::onToggleMute()
+{
+ focusOnTarget();
+
+ LLViewerMediaImpl* media_impl = getTargetMediaImpl();
+ if (media_impl)
+ {
+ F32 volume = media_impl->getVolume();
+
+ if(volume > 0.0)
+ {
+ media_impl->setVolume(0.0);
+ }
+ else
+ {
+ media_impl->setVolume(0.5);
+ }
+ }
+}
+
diff --git a/indra/newview/llpanelprimmediacontrols.h b/indra/newview/llpanelprimmediacontrols.h
new file mode 100644
index 0000000000..3ec7aa2356
--- /dev/null
+++ b/indra/newview/llpanelprimmediacontrols.h
@@ -0,0 +1,148 @@
+/**
+ * @file llpanelprimmediacontrols.h
+ * @brief Pop-up media controls panel
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ *
+ * Copyright (c) 2003-2007, 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://secondlife.com/developers/opensource/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://secondlife.com/developers/opensource/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_PANELPRIMMEDIACONTROLS_H
+#define LL_PANELPRIMMEDIACONTROLS_H
+
+#include "llpanel.h"
+#include "llviewermedia.h"
+
+class LLCoordWindow;
+class LLViewerMediaImpl;
+
+class LLPanelPrimMediaControls : public LLPanel
+{
+public:
+ LLPanelPrimMediaControls();
+ virtual ~LLPanelPrimMediaControls();
+ /*virtual*/ BOOL postBuild();
+ virtual void draw();
+ virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
+
+ virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
+ virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
+ virtual BOOL handleKeyHere(KEY key, MASK mask);
+
+ void updateShape();
+ bool isMouseOver();
+ void nextZoomLevel();
+ void resetZoomLevel();
+ void close();
+
+ LLHandle<LLPanelPrimMediaControls> getHandle() const { return mPanelHandle; }
+ void setMediaFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal = LLVector3::zero);
+
+
+ enum EZoomLevel
+ {
+ ZOOM_NONE = 0,
+ ZOOM_FAR,
+ ZOOM_MEDIUM,
+ ZOOM_NEAR
+ };
+ static const EZoomLevel kZoomLevels[];
+ static const int kNumZoomLevels;
+
+ enum EScrollDir
+ {
+ SCROLL_UP = 0,
+ SCROLL_DOWN,
+ SCROLL_LEFT,
+ SCROLL_RIGHT,
+ SCROLL_NONE
+ };
+
+private:
+ void onClickClose();
+ void onClickBack();
+ void onClickForward();
+ void onClickHome();
+ void onClickOpen();
+ void onClickReload();
+ void onClickPlay();
+ void onClickPause();
+ void onClickStop();
+ void onClickZoom();
+ void onCommitURL();
+
+ void updateZoom();
+ void setCurrentURL();
+ void onCommitSlider();
+
+ void onCommitVolumeUp();
+ void onCommitVolumeDown();
+ void onToggleMute();
+
+ static void onScrollUp(void* user_data);
+ static void onScrollUpHeld(void* user_data);
+ static void onScrollLeft(void* user_data);
+ static void onScrollLeftHeld(void* user_data);
+ static void onScrollRight(void* user_data);
+ static void onScrollRightHeld(void* user_data);
+ static void onScrollDown(void* user_data);
+ static void onScrollDownHeld(void* user_data);
+ static void onScrollStop(void* user_data);
+
+ static void onInputURL(LLFocusableElement* caller, void *userdata);
+ static bool hasControlsPermission(LLViewerObject *obj, const LLMediaEntry *media_entry);
+
+ void focusOnTarget();
+
+ LLViewerMediaImpl* getTargetMediaImpl();
+ LLViewerObject* getTargetObject();
+ LLPluginClassMedia* getTargetMediaPlugin();
+ bool mPauseFadeout;
+ bool mUpdateSlider;
+ bool mClearFaceOnFade;
+
+ LLMatrix4 mLastCameraMat;
+ EZoomLevel mCurrentZoom;
+ EScrollDir mScrollState;
+ LLCoordWindow mLastCursorPos;
+ LLFrameTimer mInactivityTimer;
+ LLFrameTimer mFadeTimer;
+ F32 mInactiveTimeout;
+ F32 mControlFadeTime;
+ LLRootHandle<LLPanelPrimMediaControls> mPanelHandle;
+ F32 mAlpha;
+ std::string mCurrentURL;
+ std::string mPreviousURL;
+ F64 mCurrentRate;
+ F64 mMovieDuration;
+ int mUpdatePercent;
+
+ LLUUID mTargetObjectID;
+ S32 mTargetObjectFace;
+ LLUUID mTargetImplID;
+ LLVector3 mTargetObjectNormal;
+};
+
+#endif // LL_PANELPRIMMEDIACONTROLS_H
diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp
index 25e773e8b8..e97eb1df2b 100644
--- a/indra/newview/llparticipantlist.cpp
+++ b/indra/newview/llparticipantlist.cpp
@@ -34,7 +34,7 @@
#include "llparticipantlist.h"
#include "llavatarlist.h"
-#include "llfloateractivespeakers.h"
+#include "llspeakers.h"
//LLParticipantList retrieves add, clear and remove events and updates view accordingly
LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list):
@@ -48,6 +48,18 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av
mSpeakerMgr->addListener(mSpeakerAddListener, "add");
mSpeakerMgr->addListener(mSpeakerRemoveListener, "remove");
mSpeakerMgr->addListener(mSpeakerClearListener, "clear");
+
+ //Lets fill avatarList with existing speakers
+ LLAvatarList::uuid_vector_t& group_members = mAvatarList->getIDs();
+
+ LLSpeakerMgr::speaker_list_t speaker_list;
+ mSpeakerMgr->getSpeakerList(&speaker_list, true);
+ for(LLSpeakerMgr::speaker_list_t::iterator it = speaker_list.begin(); it != speaker_list.end(); it++)
+ {
+ group_members.push_back((*it)->mID);
+ }
+ mAvatarList->setDirty();
+ mAvatarList->sortByName();
}
LLParticipantList::~LLParticipantList()
@@ -87,8 +99,12 @@ bool LLParticipantList::SpeakerAddListener::handleEvent(LLPointer<LLOldEvents::L
bool LLParticipantList::SpeakerRemoveListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
{
LLAvatarList::uuid_vector_t& group_members = mAvatarList->getIDs();
- group_members.erase(std::find(group_members.begin(), group_members.end(), event->getValue().asUUID()));
- mAvatarList->setDirty();
+ LLAvatarList::uuid_vector_t::iterator pos = std::find(group_members.begin(), group_members.end(), event->getValue().asUUID());
+ if(pos != group_members.end())
+ {
+ group_members.erase(pos);
+ mAvatarList->setDirty();
+ }
return true;
}
diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp
index 1683d113a9..e4dbcbd219 100644
--- a/indra/newview/llscreenchannel.cpp
+++ b/indra/newview/llscreenchannel.cpp
@@ -44,7 +44,6 @@
#include "lltrans.h"
#include "lldockablefloater.h"
-#include "llimpanel.h"
#include "llsyswellwindow.h"
#include "llimfloater.h"
@@ -191,19 +190,22 @@ void LLScreenChannel::onToastFade(LLToast* toast)
{
std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), static_cast<LLPanel*>(toast));
- bool delete_toast = !mCanStoreToasts || !toast->getCanBeStored();
- if(delete_toast)
- {
- mToastList.erase(it);
- deleteToast(toast);
- }
- else
+ if(it != mToastList.end())
{
- storeToast((*it));
- mToastList.erase(it);
- }
+ bool delete_toast = !mCanStoreToasts || !toast->getCanBeStored();
+ if(delete_toast)
+ {
+ mToastList.erase(it);
+ deleteToast(toast);
+ }
+ else
+ {
+ storeToast((*it));
+ mToastList.erase(it);
+ }
- redrawToasts();
+ redrawToasts();
+ }
}
//--------------------------------------------------------------------------
@@ -247,6 +249,7 @@ void LLScreenChannel::loadStoredToastsToChannel()
for(it = mStoredToastList.begin(); it != mStoredToastList.end(); ++it)
{
+ (*it).toast->setIsHidden(false);
(*it).toast->resetTimer();
mToastList.push_back((*it));
}
@@ -266,6 +269,7 @@ void LLScreenChannel::loadStoredToastByNotificationIDToChannel(LLUUID id)
mOverflowToastHidden = false;
LLToast* toast = (*it).toast;
+ toast->setIsHidden(false);
toast->resetTimer();
mToastList.push_back((*it));
mStoredToastList.erase(it);
@@ -519,6 +523,7 @@ void LLScreenChannel::createStartUpToast(S32 notif_num, F32 timer)
LLRect toast_rect;
LLToast::Params p;
p.lifetime_secs = timer;
+ p.enable_hide_btn = false;
mStartUpToastPanel = new LLToast(p);
if(!mStartUpToastPanel)
diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp
new file mode 100644
index 0000000000..2341fcfc6d
--- /dev/null
+++ b/indra/newview/llspeakers.cpp
@@ -0,0 +1,639 @@
+/**
+ * @file llspeakers.cpp
+ * @brief Management interface for muting and controlling volume of residents currently speaking
+ *
+ * $LicenseInfo:firstyear=2005&license=viewergpl$
+ *
+ * Copyright (c) 2005-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 "llspeakers.h"
+
+#include "llagent.h"
+#include "llappviewer.h"
+#include "llmutelist.h"
+#include "llsdutil.h"
+#include "lluicolortable.h"
+#include "llviewerobjectlist.h"
+#include "llvoavatar.h"
+#include "llworld.h"
+
+const F32 SPEAKER_TIMEOUT = 10.f; // seconds of not being on voice channel before removed from list of active speakers
+const LLColor4 INACTIVE_COLOR(0.3f, 0.3f, 0.3f, 0.5f);
+const LLColor4 ACTIVE_COLOR(0.5f, 0.5f, 0.5f, 1.f);
+
+LLSpeaker::LLSpeaker(const LLUUID& id, const std::string& name, const ESpeakerType type) :
+ mStatus(LLSpeaker::STATUS_TEXT_ONLY),
+ mLastSpokeTime(0.f),
+ mSpeechVolume(0.f),
+ mHasSpoken(FALSE),
+ mHasLeftCurrentCall(FALSE),
+ mDotColor(LLColor4::white),
+ mID(id),
+ mTyping(FALSE),
+ mSortIndex(0),
+ mType(type),
+ mIsModerator(FALSE),
+ mModeratorMutedVoice(FALSE),
+ mModeratorMutedText(FALSE)
+{
+ if (name.empty() && type == SPEAKER_AGENT)
+ {
+ lookupName();
+ }
+ else
+ {
+ mDisplayName = name;
+ }
+
+ gVoiceClient->setUserVolume(id, LLMuteList::getInstance()->getSavedResidentVolume(id));
+
+ mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
+}
+
+
+void LLSpeaker::lookupName()
+{
+ gCacheName->get(mID, FALSE, boost::bind(&LLSpeaker::onAvatarNameLookup, this, _1, _2, _3, _4));
+}
+
+void LLSpeaker::onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group)
+{
+ mDisplayName = first + " " + last;
+}
+
+LLSpeakerTextModerationEvent::LLSpeakerTextModerationEvent(LLSpeaker* source)
+: LLEvent(source, "Speaker text moderation event")
+{
+}
+
+LLSD LLSpeakerTextModerationEvent::getValue()
+{
+ return std::string("text");
+}
+
+
+LLSpeakerVoiceModerationEvent::LLSpeakerVoiceModerationEvent(LLSpeaker* source)
+: LLEvent(source, "Speaker voice moderation event")
+{
+}
+
+LLSD LLSpeakerVoiceModerationEvent::getValue()
+{
+ return std::string("voice");
+}
+
+LLSpeakerListChangeEvent::LLSpeakerListChangeEvent(LLSpeakerMgr* source, const LLUUID& speaker_id)
+: LLEvent(source, "Speaker added/removed from speaker mgr"),
+ mSpeakerID(speaker_id)
+{
+}
+
+LLSD LLSpeakerListChangeEvent::getValue()
+{
+ return mSpeakerID;
+}
+
+// helper sort class
+struct LLSortRecentSpeakers
+{
+ bool operator()(const LLPointer<LLSpeaker> lhs, const LLPointer<LLSpeaker> rhs) const;
+};
+
+bool LLSortRecentSpeakers::operator()(const LLPointer<LLSpeaker> lhs, const LLPointer<LLSpeaker> rhs) const
+{
+ // Sort first on status
+ if (lhs->mStatus != rhs->mStatus)
+ {
+ return (lhs->mStatus < rhs->mStatus);
+ }
+
+ // and then on last speaking time
+ if(lhs->mLastSpokeTime != rhs->mLastSpokeTime)
+ {
+ return (lhs->mLastSpokeTime > rhs->mLastSpokeTime);
+ }
+
+ // and finally (only if those are both equal), on name.
+ return( lhs->mDisplayName.compare(rhs->mDisplayName) < 0 );
+}
+
+
+//
+// LLSpeakerMgr
+//
+
+LLSpeakerMgr::LLSpeakerMgr(LLVoiceChannel* channelp) :
+ mVoiceChannel(channelp)
+{
+}
+
+LLSpeakerMgr::~LLSpeakerMgr()
+{
+}
+
+LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::string& name, LLSpeaker::ESpeakerStatus status, LLSpeaker::ESpeakerType type)
+{
+ if (id.isNull()) return NULL;
+
+ LLPointer<LLSpeaker> speakerp;
+ if (mSpeakers.find(id) == mSpeakers.end())
+ {
+ speakerp = new LLSpeaker(id, name, type);
+ speakerp->mStatus = status;
+ mSpeakers.insert(std::make_pair(speakerp->mID, speakerp));
+ mSpeakersSorted.push_back(speakerp);
+ fireEvent(new LLSpeakerListChangeEvent(this, speakerp->mID), "add");
+ }
+ else
+ {
+ speakerp = findSpeaker(id);
+ if (speakerp.notNull())
+ {
+ // keep highest priority status (lowest value) instead of overriding current value
+ speakerp->mStatus = llmin(speakerp->mStatus, status);
+ speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
+ // RN: due to a weird behavior where IMs from attached objects come from the wearer's agent_id
+ // we need to override speakers that we think are objects when we find out they are really
+ // residents
+ if (type == LLSpeaker::SPEAKER_AGENT)
+ {
+ speakerp->mType = LLSpeaker::SPEAKER_AGENT;
+ speakerp->lookupName();
+ }
+ }
+ }
+
+ return speakerp;
+}
+
+void LLSpeakerMgr::update(BOOL resort_ok)
+{
+ if (!gVoiceClient)
+ {
+ return;
+ }
+
+ LLColor4 speaking_color = LLUIColorTable::instance().getColor("SpeakingColor");
+ LLColor4 overdriven_color = LLUIColorTable::instance().getColor("OverdrivenColor");
+
+ if(resort_ok) // only allow list changes when user is not interacting with it
+ {
+ updateSpeakerList();
+ }
+
+ // update status of all current speakers
+ BOOL voice_channel_active = (!mVoiceChannel && gVoiceClient->inProximalChannel()) || (mVoiceChannel && mVoiceChannel->isActive());
+ for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end();)
+ {
+ LLUUID speaker_id = speaker_it->first;
+ LLSpeaker* speakerp = speaker_it->second;
+
+ speaker_map_t::iterator cur_speaker_it = speaker_it++;
+
+ if (voice_channel_active && gVoiceClient->getVoiceEnabled(speaker_id))
+ {
+ speakerp->mSpeechVolume = gVoiceClient->getCurrentPower(speaker_id);
+ BOOL moderator_muted_voice = gVoiceClient->getIsModeratorMuted(speaker_id);
+ if (moderator_muted_voice != speakerp->mModeratorMutedVoice)
+ {
+ speakerp->mModeratorMutedVoice = moderator_muted_voice;
+ speakerp->fireEvent(new LLSpeakerVoiceModerationEvent(speakerp));
+ }
+
+ if (gVoiceClient->getOnMuteList(speaker_id) || speakerp->mModeratorMutedVoice)
+ {
+ speakerp->mStatus = LLSpeaker::STATUS_MUTED;
+ }
+ else if (gVoiceClient->getIsSpeaking(speaker_id))
+ {
+ // reset inactivity expiration
+ if (speakerp->mStatus != LLSpeaker::STATUS_SPEAKING)
+ {
+ speakerp->mLastSpokeTime = mSpeechTimer.getElapsedTimeF32();
+ speakerp->mHasSpoken = TRUE;
+ }
+ speakerp->mStatus = LLSpeaker::STATUS_SPEAKING;
+ // interpolate between active color and full speaking color based on power of speech output
+ speakerp->mDotColor = speaking_color;
+ if (speakerp->mSpeechVolume > LLVoiceClient::OVERDRIVEN_POWER_LEVEL)
+ {
+ speakerp->mDotColor = overdriven_color;
+ }
+ }
+ else
+ {
+ speakerp->mSpeechVolume = 0.f;
+ speakerp->mDotColor = ACTIVE_COLOR;
+
+ if (speakerp->mHasSpoken)
+ {
+ // have spoken once, not currently speaking
+ speakerp->mStatus = LLSpeaker::STATUS_HAS_SPOKEN;
+ }
+ else
+ {
+ // default state for being in voice channel
+ speakerp->mStatus = LLSpeaker::STATUS_VOICE_ACTIVE;
+ }
+ }
+ }
+ // speaker no longer registered in voice channel, demote to text only
+ else if (speakerp->mStatus != LLSpeaker::STATUS_NOT_IN_CHANNEL)
+ {
+ if(speakerp->mType == LLSpeaker::SPEAKER_EXTERNAL)
+ {
+ // external speakers should be timed out when they leave the voice channel (since they only exist via SLVoice)
+ speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
+ }
+ else
+ {
+ speakerp->mStatus = LLSpeaker::STATUS_TEXT_ONLY;
+ speakerp->mSpeechVolume = 0.f;
+ speakerp->mDotColor = ACTIVE_COLOR;
+ }
+ }
+ }
+
+ if(resort_ok) // only allow list changes when user is not interacting with it
+ {
+ // sort by status then time last spoken
+ std::sort(mSpeakersSorted.begin(), mSpeakersSorted.end(), LLSortRecentSpeakers());
+ }
+
+ // for recent speakers who are not currently speaking, show "recent" color dot for most recent
+ // fading to "active" color
+
+ S32 recent_speaker_count = 0;
+ S32 sort_index = 0;
+ speaker_list_t::iterator sorted_speaker_it;
+ for(sorted_speaker_it = mSpeakersSorted.begin();
+ sorted_speaker_it != mSpeakersSorted.end(); )
+ {
+ LLPointer<LLSpeaker> speakerp = *sorted_speaker_it;
+
+ // color code recent speakers who are not currently speaking
+ if (speakerp->mStatus == LLSpeaker::STATUS_HAS_SPOKEN)
+ {
+ speakerp->mDotColor = lerp(speaking_color, ACTIVE_COLOR, clamp_rescale((F32)recent_speaker_count, -2.f, 3.f, 0.f, 1.f));
+ recent_speaker_count++;
+ }
+
+ // stuff sort ordinal into speaker so the ui can sort by this value
+ speakerp->mSortIndex = sort_index++;
+
+ // remove speakers that have been gone too long
+ if (speakerp->mStatus == LLSpeaker::STATUS_NOT_IN_CHANNEL && speakerp->mActivityTimer.hasExpired())
+ {
+ fireEvent(new LLSpeakerListChangeEvent(this, speakerp->mID), "remove");
+
+ mSpeakers.erase(speakerp->mID);
+ sorted_speaker_it = mSpeakersSorted.erase(sorted_speaker_it);
+ }
+ else
+ {
+ ++sorted_speaker_it;
+ }
+ }
+}
+
+void LLSpeakerMgr::updateSpeakerList()
+{
+ // are we bound to the currently active voice channel?
+ if ((!mVoiceChannel && gVoiceClient->inProximalChannel()) || (mVoiceChannel && mVoiceChannel->isActive()))
+ {
+ LLVoiceClient::participantMap* participants = gVoiceClient->getParticipantList();
+ if(participants)
+ {
+ LLVoiceClient::participantMap::iterator participant_it;
+
+ // add new participants to our list of known speakers
+ for (participant_it = participants->begin(); participant_it != participants->end(); ++participant_it)
+ {
+ LLVoiceClient::participantState* participantp = participant_it->second;
+ setSpeaker(participantp->mAvatarID, participantp->mDisplayName, LLSpeaker::STATUS_VOICE_ACTIVE, (participantp->isAvatar()?LLSpeaker::SPEAKER_AGENT:LLSpeaker::SPEAKER_EXTERNAL));
+ }
+ }
+ }
+}
+
+LLPointer<LLSpeaker> LLSpeakerMgr::findSpeaker(const LLUUID& speaker_id)
+{
+ speaker_map_t::iterator found_it = mSpeakers.find(speaker_id);
+ if (found_it == mSpeakers.end())
+ {
+ return NULL;
+ }
+ return found_it->second;
+}
+
+void LLSpeakerMgr::getSpeakerList(speaker_list_t* speaker_list, BOOL include_text)
+{
+ speaker_list->clear();
+ for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); ++speaker_it)
+ {
+ LLPointer<LLSpeaker> speakerp = speaker_it->second;
+ // what about text only muted or inactive?
+ if (include_text || speakerp->mStatus != LLSpeaker::STATUS_TEXT_ONLY)
+ {
+ speaker_list->push_back(speakerp);
+ }
+ }
+}
+
+const LLUUID LLSpeakerMgr::getSessionID()
+{
+ return mVoiceChannel->getSessionID();
+}
+
+
+void LLSpeakerMgr::setSpeakerTyping(const LLUUID& speaker_id, BOOL typing)
+{
+ LLPointer<LLSpeaker> speakerp = findSpeaker(speaker_id);
+ if (speakerp.notNull())
+ {
+ speakerp->mTyping = typing;
+ }
+}
+
+// speaker has chatted via either text or voice
+void LLSpeakerMgr::speakerChatted(const LLUUID& speaker_id)
+{
+ LLPointer<LLSpeaker> speakerp = findSpeaker(speaker_id);
+ if (speakerp.notNull())
+ {
+ speakerp->mLastSpokeTime = mSpeechTimer.getElapsedTimeF32();
+ speakerp->mHasSpoken = TRUE;
+ }
+}
+
+BOOL LLSpeakerMgr::isVoiceActive()
+{
+ // mVoiceChannel = NULL means current voice channel, whatever it is
+ return LLVoiceClient::voiceEnabled() && mVoiceChannel && mVoiceChannel->isActive();
+}
+
+
+//
+// LLIMSpeakerMgr
+//
+LLIMSpeakerMgr::LLIMSpeakerMgr(LLVoiceChannel* channel) : LLSpeakerMgr(channel)
+{
+}
+
+void LLIMSpeakerMgr::updateSpeakerList()
+{
+ // don't do normal updates which are pulled from voice channel
+ // rely on user list reported by sim
+
+ // We need to do this to allow PSTN callers into group chats to show in the list.
+ LLSpeakerMgr::updateSpeakerList();
+
+ return;
+}
+
+void LLIMSpeakerMgr::setSpeakers(const LLSD& speakers)
+{
+ if ( !speakers.isMap() ) return;
+
+ if ( speakers.has("agent_info") && speakers["agent_info"].isMap() )
+ {
+ LLSD::map_const_iterator speaker_it;
+ for(speaker_it = speakers["agent_info"].beginMap();
+ speaker_it != speakers["agent_info"].endMap();
+ ++speaker_it)
+ {
+ LLUUID agent_id(speaker_it->first);
+
+ LLPointer<LLSpeaker> speakerp = setSpeaker(
+ agent_id,
+ LLStringUtil::null,
+ LLSpeaker::STATUS_TEXT_ONLY);
+
+ if ( speaker_it->second.isMap() )
+ {
+ speakerp->mIsModerator = speaker_it->second["is_moderator"];
+ speakerp->mModeratorMutedText =
+ speaker_it->second["mutes"]["text"];
+ }
+ }
+ }
+ else if ( speakers.has("agents" ) && speakers["agents"].isArray() )
+ {
+ //older, more decprecated way. Need here for
+ //using older version of servers
+ LLSD::array_const_iterator speaker_it;
+ for(speaker_it = speakers["agents"].beginArray();
+ speaker_it != speakers["agents"].endArray();
+ ++speaker_it)
+ {
+ const LLUUID agent_id = (*speaker_it).asUUID();
+
+ LLPointer<LLSpeaker> speakerp = setSpeaker(
+ agent_id,
+ LLStringUtil::null,
+ LLSpeaker::STATUS_TEXT_ONLY);
+ }
+ }
+}
+
+void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
+{
+ if ( !update.isMap() ) return;
+
+ if ( update.has("agent_updates") && update["agent_updates"].isMap() )
+ {
+ LLSD::map_const_iterator update_it;
+ for(
+ update_it = update["agent_updates"].beginMap();
+ update_it != update["agent_updates"].endMap();
+ ++update_it)
+ {
+ LLUUID agent_id(update_it->first);
+ LLPointer<LLSpeaker> speakerp = findSpeaker(agent_id);
+
+ LLSD agent_data = update_it->second;
+
+ if (agent_data.isMap() && agent_data.has("transition"))
+ {
+ if (agent_data["transition"].asString() == "LEAVE" && speakerp.notNull())
+ {
+ speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
+ speakerp->mDotColor = INACTIVE_COLOR;
+ speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
+ }
+ else if (agent_data["transition"].asString() == "ENTER")
+ {
+ // add or update speaker
+ speakerp = setSpeaker(agent_id);
+ }
+ else
+ {
+ llwarns << "bad membership list update " << ll_print_sd(agent_data["transition"]) << llendl;
+ }
+ }
+
+ if (speakerp.isNull()) continue;
+
+ // should have a valid speaker from this point on
+ if (agent_data.isMap() && agent_data.has("info"))
+ {
+ LLSD agent_info = agent_data["info"];
+
+ if (agent_info.has("is_moderator"))
+ {
+ speakerp->mIsModerator = agent_info["is_moderator"];
+ }
+
+ if (agent_info.has("mutes"))
+ {
+ speakerp->mModeratorMutedText = agent_info["mutes"]["text"];
+ }
+ }
+ }
+ }
+ else if ( update.has("updates") && update["updates"].isMap() )
+ {
+ LLSD::map_const_iterator update_it;
+ for (
+ update_it = update["updates"].beginMap();
+ update_it != update["updates"].endMap();
+ ++update_it)
+ {
+ LLUUID agent_id(update_it->first);
+ LLPointer<LLSpeaker> speakerp = findSpeaker(agent_id);
+
+ std::string agent_transition = update_it->second.asString();
+ if (agent_transition == "LEAVE" && speakerp.notNull())
+ {
+ speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
+ speakerp->mDotColor = INACTIVE_COLOR;
+ speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
+ }
+ else if ( agent_transition == "ENTER")
+ {
+ // add or update speaker
+ speakerp = setSpeaker(agent_id);
+ }
+ else
+ {
+ llwarns << "bad membership list update "
+ << agent_transition << llendl;
+ }
+ }
+ }
+}
+
+
+//
+// LLActiveSpeakerMgr
+//
+
+LLActiveSpeakerMgr::LLActiveSpeakerMgr() : LLSpeakerMgr(NULL)
+{
+}
+
+void LLActiveSpeakerMgr::updateSpeakerList()
+{
+ // point to whatever the current voice channel is
+ mVoiceChannel = LLVoiceChannel::getCurrentVoiceChannel();
+
+ // always populate from active voice channel
+ if (LLVoiceChannel::getCurrentVoiceChannel() != mVoiceChannel)
+ {
+ fireEvent(new LLSpeakerListChangeEvent(this, LLUUID::null), "clear");
+ mSpeakers.clear();
+ mSpeakersSorted.clear();
+ mVoiceChannel = LLVoiceChannel::getCurrentVoiceChannel();
+ }
+ LLSpeakerMgr::updateSpeakerList();
+
+ // clean up text only speakers
+ for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); ++speaker_it)
+ {
+ LLUUID speaker_id = speaker_it->first;
+ LLSpeaker* speakerp = speaker_it->second;
+ if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY)
+ {
+ // automatically flag text only speakers for removal
+ speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
+ }
+ }
+
+}
+
+
+
+//
+// LLLocalSpeakerMgr
+//
+
+LLLocalSpeakerMgr::LLLocalSpeakerMgr() : LLSpeakerMgr(LLVoiceChannelProximal::getInstance())
+{
+}
+
+LLLocalSpeakerMgr::~LLLocalSpeakerMgr ()
+{
+}
+
+void LLLocalSpeakerMgr::updateSpeakerList()
+{
+ // pull speakers from voice channel
+ LLSpeakerMgr::updateSpeakerList();
+
+ if (gDisconnected)//the world is cleared.
+ {
+ return ;
+ }
+
+ // pick up non-voice speakers in chat range
+ std::vector<LLUUID> avatar_ids;
+ std::vector<LLVector3d> positions;
+ LLWorld::getInstance()->getAvatars(&avatar_ids, &positions, gAgent.getPositionGlobal(), CHAT_NORMAL_RADIUS);
+ for(U32 i=0; i<avatar_ids.size(); i++)
+ {
+ setSpeaker(avatar_ids[i]);
+ }
+
+ // check if text only speakers have moved out of chat range
+ for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); ++speaker_it)
+ {
+ LLUUID speaker_id = speaker_it->first;
+ LLSpeaker* speakerp = speaker_it->second;
+ if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY)
+ {
+ LLVOAvatar* avatarp = (LLVOAvatar*)gObjectList.findObject(speaker_id);
+ if (!avatarp || dist_vec(avatarp->getPositionAgent(), gAgent.getPositionAgent()) > CHAT_NORMAL_RADIUS)
+ {
+ speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
+ speakerp->mDotColor = INACTIVE_COLOR;
+ speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
+ }
+ }
+ }
+}
diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h
new file mode 100644
index 0000000000..e0f22bff4f
--- /dev/null
+++ b/indra/newview/llspeakers.h
@@ -0,0 +1,172 @@
+/**
+ * @file llspeakers.h
+ * @brief Management interface for muting and controlling volume of residents currently speaking
+ *
+ * $LicenseInfo:firstyear=2005&license=viewergpl$
+ *
+ * Copyright (c) 2005-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_LLSPEAKERS_H
+#define LL_LLSPEAKERS_H
+
+#include "llevent.h"
+#include "llspeakers.h"
+#include "llvoicechannel.h"
+
+class LLSpeakerMgr;
+
+// data for a given participant in a voice channel
+class LLSpeaker : public LLRefCount, public LLOldEvents::LLObservable, public LLHandleProvider<LLSpeaker>, public boost::signals2::trackable
+{
+public:
+ typedef enum e_speaker_type
+ {
+ SPEAKER_AGENT,
+ SPEAKER_OBJECT,
+ SPEAKER_EXTERNAL // Speaker that doesn't map to an avatar or object (i.e. PSTN caller in a group)
+ } ESpeakerType;
+
+ typedef enum e_speaker_status
+ {
+ STATUS_SPEAKING,
+ STATUS_HAS_SPOKEN,
+ STATUS_VOICE_ACTIVE,
+ STATUS_TEXT_ONLY,
+ STATUS_NOT_IN_CHANNEL,
+ STATUS_MUTED
+ } ESpeakerStatus;
+
+
+ LLSpeaker(const LLUUID& id, const std::string& name = LLStringUtil::null, const ESpeakerType type = SPEAKER_AGENT);
+ ~LLSpeaker() {};
+ void lookupName();
+
+ void onAvatarNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group);
+
+ ESpeakerStatus mStatus; // current activity status in speech group
+ F32 mLastSpokeTime; // timestamp when this speaker last spoke
+ F32 mSpeechVolume; // current speech amplitude (timea average rms amplitude?)
+ std::string mDisplayName; // cache user name for this speaker
+ LLFrameTimer mActivityTimer; // time out speakers when they are not part of current voice channel
+ BOOL mHasSpoken; // has this speaker said anything this session?
+ BOOL mHasLeftCurrentCall; // has this speaker left the current voice call?
+ LLColor4 mDotColor;
+ LLUUID mID;
+ BOOL mTyping;
+ S32 mSortIndex;
+ ESpeakerType mType;
+ BOOL mIsModerator;
+ BOOL mModeratorMutedVoice;
+ BOOL mModeratorMutedText;
+};
+
+class LLSpeakerTextModerationEvent : public LLOldEvents::LLEvent
+{
+public:
+ LLSpeakerTextModerationEvent(LLSpeaker* source);
+ /*virtual*/ LLSD getValue();
+};
+
+class LLSpeakerVoiceModerationEvent : public LLOldEvents::LLEvent
+{
+public:
+ LLSpeakerVoiceModerationEvent(LLSpeaker* source);
+ /*virtual*/ LLSD getValue();
+};
+
+class LLSpeakerListChangeEvent : public LLOldEvents::LLEvent
+{
+public:
+ LLSpeakerListChangeEvent(LLSpeakerMgr* source, const LLUUID& speaker_id);
+ /*virtual*/ LLSD getValue();
+
+private:
+ const LLUUID& mSpeakerID;
+};
+
+class LLSpeakerMgr : public LLOldEvents::LLObservable
+{
+public:
+ LLSpeakerMgr(LLVoiceChannel* channelp);
+ virtual ~LLSpeakerMgr();
+
+ LLPointer<LLSpeaker> findSpeaker(const LLUUID& avatar_id);
+ void update(BOOL resort_ok);
+ void setSpeakerTyping(const LLUUID& speaker_id, BOOL typing);
+ void speakerChatted(const LLUUID& speaker_id);
+ LLPointer<LLSpeaker> setSpeaker(const LLUUID& id,
+ const std::string& name = LLStringUtil::null,
+ LLSpeaker::ESpeakerStatus status = LLSpeaker::STATUS_TEXT_ONLY,
+ LLSpeaker::ESpeakerType = LLSpeaker::SPEAKER_AGENT);
+
+ BOOL isVoiceActive();
+
+ typedef std::vector<LLPointer<LLSpeaker> > speaker_list_t;
+ void getSpeakerList(speaker_list_t* speaker_list, BOOL include_text);
+ LLVoiceChannel* getVoiceChannel() { return mVoiceChannel; }
+ const LLUUID getSessionID();
+
+protected:
+ virtual void updateSpeakerList();
+
+ typedef std::map<LLUUID, LLPointer<LLSpeaker> > speaker_map_t;
+ speaker_map_t mSpeakers;
+
+ speaker_list_t mSpeakersSorted;
+ LLFrameTimer mSpeechTimer;
+ LLVoiceChannel* mVoiceChannel;
+};
+
+class LLIMSpeakerMgr : public LLSpeakerMgr
+{
+public:
+ LLIMSpeakerMgr(LLVoiceChannel* channel);
+
+ void updateSpeakers(const LLSD& update);
+ void setSpeakers(const LLSD& speakers);
+protected:
+ virtual void updateSpeakerList();
+};
+
+class LLActiveSpeakerMgr : public LLSpeakerMgr, public LLSingleton<LLActiveSpeakerMgr>
+{
+public:
+ LLActiveSpeakerMgr();
+protected:
+ virtual void updateSpeakerList();
+};
+
+class LLLocalSpeakerMgr : public LLSpeakerMgr, public LLSingleton<LLLocalSpeakerMgr>
+{
+public:
+ LLLocalSpeakerMgr();
+ ~LLLocalSpeakerMgr ();
+protected:
+ virtual void updateSpeakerList();
+};
+
+#endif // LL_LLSPEAKERS_H
diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp
index 86290e6695..93a931dc78 100644
--- a/indra/newview/llsyswellwindow.cpp
+++ b/indra/newview/llsyswellwindow.cpp
@@ -113,6 +113,12 @@ void LLSysWellWindow::connectListUpdaterToSignal(std::string notification_type)
}
//---------------------------------------------------------------------------------
+void LLSysWellWindow::onStartUpToastClick(S32 x, S32 y, MASK mask)
+{
+ onChicletClick();
+}
+
+//---------------------------------------------------------------------------------
void LLSysWellWindow::onChicletClick()
{
// 1 - remove StartUp toast and channel if present
diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h
index fa6a1abea4..cbc5f7358f 100644
--- a/indra/newview/llsyswellwindow.h
+++ b/indra/newview/llsyswellwindow.h
@@ -76,6 +76,7 @@ public:
void onItemClose(LLSysWellItem* item);
void onStoreToast(LLPanel* info_panel, LLUUID id);
void onChicletClick();
+ void onStartUpToastClick(S32 x, S32 y, MASK mask);
// size constants for the window and for its elements
static const S32 MAX_WINDOW_HEIGHT = 200;
diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp
index 17547cae39..5d9046ac90 100644
--- a/indra/newview/lltexlayer.cpp
+++ b/indra/newview/lltexlayer.cpp
@@ -804,8 +804,9 @@ void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height,
gGL.setColorMask(false, true);
gGL.setSceneBlendType(LLRender::BT_REPLACE);
+
// (Optionally) replace alpha with a single component image from a tga file.
- if (!info->mStaticAlphaFileName.empty() && mMaskLayerList.empty())
+ if (!info->mStaticAlphaFileName.empty())
{
LLGLSNoAlphaTest gls_no_alpha_test;
gGL.flush();
diff --git a/indra/newview/lltexlayerparams.cpp b/indra/newview/lltexlayerparams.cpp
index e1643af71d..74e0fa077e 100644
--- a/indra/newview/lltexlayerparams.cpp
+++ b/indra/newview/lltexlayerparams.cpp
@@ -42,8 +42,7 @@
//-----------------------------------------------------------------------------
LLTexLayerParam::LLTexLayerParam(LLTexLayerInterface *layer) :
mTexLayer(layer),
- mAvatar(NULL),
- mIsWearableParam(TRUE)
+ mAvatar(NULL)
{
if (mTexLayer != NULL)
{
@@ -56,8 +55,7 @@ LLTexLayerParam::LLTexLayerParam(LLTexLayerInterface *layer) :
}
LLTexLayerParam::LLTexLayerParam(LLVOAvatar *avatar) :
- mTexLayer(NULL),
- mIsWearableParam(FALSE)
+ mTexLayer(NULL)
{
mAvatar = avatar;
}
@@ -177,7 +175,7 @@ void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL set_by_user)
{
mCurWeight = new_weight;
- if ((mAvatar->getSex() & getSex()) && !mIsWearableParam) // only trigger a baked texture update if we're changing a wearable's visual param.
+ if ((mAvatar->getSex() & getSex()) && (mAvatar->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param.
{
if (gAgent.cameraCustomizeAvatar())
{
@@ -192,6 +190,13 @@ void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL set_by_user)
void LLTexLayerParamAlpha::setAnimationTarget(F32 target_value, BOOL set_by_user)
{
+ // do not animate dummy parameters
+ if (mIsDummy)
+ {
+ setWeight(target_value, set_by_user);
+ return;
+ }
+
mTargetWeight = target_value;
setWeight(target_value, set_by_user);
mIsAnimating = TRUE;
@@ -468,7 +473,7 @@ void LLTexLayerParamColor::setWeight(F32 weight, BOOL set_by_user)
return;
}
- if ((mAvatar->getSex() & getSex()) && !mIsWearableParam) // only trigger a baked texture update if we're changing a wearable's visual param.
+ if ((mAvatar->getSex() & getSex()) && (mAvatar->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param.
{
onGlobalColorChanged(set_by_user);
if (mTexLayer)
diff --git a/indra/newview/lltexlayerparams.h b/indra/newview/lltexlayerparams.h
index dcb108bbf6..98365864f9 100644
--- a/indra/newview/lltexlayerparams.h
+++ b/indra/newview/lltexlayerparams.h
@@ -49,7 +49,6 @@ public:
protected:
LLTexLayerInterface* mTexLayer;
LLVOAvatar* mAvatar;
- BOOL mIsWearableParam;
};
//-----------------------------------------------------------------------------
diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp
index eba43d76a6..24824a095c 100644
--- a/indra/newview/lltoast.cpp
+++ b/indra/newview/lltoast.cpp
@@ -63,6 +63,7 @@ LLToast::LLToast(const LLToast::Params& p)
mHideBtnEnabled(p.enable_hide_btn),
mHideBtn(NULL),
mNotification(p.notification),
+ mIsHidden(false),
mHideBtnPressed(false)
{
LLUICtrlFactory::getInstance()->buildFloater(this, "panel_toast.xml", NULL);
@@ -143,7 +144,8 @@ void LLToast::hide()
{
setVisible(FALSE);
mTimer.stop();
- mOnFadeSignal(this);
+ mIsHidden = true;
+ mOnFadeSignal(this);
}
//--------------------------------------------------------------------------
@@ -159,9 +161,7 @@ void LLToast::tick()
{
if(mCanFade)
{
- setVisible(FALSE);
- mTimer.stop();
- mOnFadeSignal(this);
+ hide();
}
}
@@ -206,6 +206,16 @@ void LLToast::draw()
//--------------------------------------------------------------------------
void LLToast::setVisible(BOOL show)
{
+ if(mIsHidden)
+ {
+ // this toast is invisible after fade until its ScreenChannel will allow it
+ //
+ // (EXT-1849) according to this bug a toast can be resurrected from
+ // invisible state if it faded during a teleportation
+ // then it fades a second time and causes a crash
+ return;
+ }
+
if(show)
{
setBackgroundOpaque(TRUE);
diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h
index 1826c13ebc..0698c94880 100644
--- a/indra/newview/lltoast.h
+++ b/indra/newview/lltoast.h
@@ -125,6 +125,8 @@ public:
void setCanBeStored(bool can_be_stored) { mCanBeStored = can_be_stored; }
//
bool getCanBeStored() { return mCanBeStored; }
+ // set whether this toast considered as hidden or not
+ void setIsHidden( bool is_toast_hidden ) { mIsHidden = is_toast_hidden; }
// Registers signals/callbacks for events
@@ -164,6 +166,7 @@ private:
bool mCanBeStored;
bool mHideBtnEnabled;
bool mHideBtnPressed;
+ bool mIsHidden; // this flag is TRUE when a toast has faded or was hidden with (x) button (EXT-1849)
};
}
diff --git a/indra/newview/lltoastimpanel.cpp b/indra/newview/lltoastimpanel.cpp
index c2cd63900b..c02fd7a5ef 100644
--- a/indra/newview/lltoastimpanel.cpp
+++ b/indra/newview/lltoastimpanel.cpp
@@ -32,7 +32,6 @@
#include "llviewerprecompiledheaders.h"
#include "lltoastimpanel.h"
-#include "llimpanel.h"
const S32 LLToastIMPanel::DEFAULT_MESSAGE_MAX_LINE_COUNT = 6;
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index 22ed1ec219..7c17699bf9 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -1049,6 +1049,9 @@ bool LLToolPie::handleMediaClick(const LLPickInfo& pick)
}
else
{
+ // Make sure keyboard focus is set to the media focus object.
+ gFocusMgr.setKeyboardFocus(LLViewerMediaFocus::getInstance());
+
media_impl->mouseDown(pick.mUVCoords, gKeyboard->currentMask(TRUE));
mMediaMouseCaptureID = mep->getMediaID();
setMouseCapture(TRUE); // This object will send a mouse-up to the media when it loses capture.
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index b71291f834..35226a1632 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -511,13 +511,34 @@ bool toggle_show_snapshot_button(const LLSD& newvalue)
bool toggle_show_navigation_panel(const LLSD& newvalue)
{
- LLNavigationBar::getInstance()->showNavigationPanel(newvalue.asBoolean());
+ LLRect floater_view_rect = gFloaterView->getRect();
+ LLRect notify_view_rect = gNotifyBoxView->getRect();
+ LLNavigationBar* navbar = LLNavigationBar::getInstance();
+
+ //if newvalue contains 0 => navbar should turn invisible, so floater_view_rect should get higher,
+ //and to do this pm=1, else if navbar becomes visible pm=-1 so floater_view_rect gets lower.
+ int pm=newvalue.asBoolean()?-1:1;
+ floater_view_rect.mTop += pm*(navbar->getDefNavBarHeight()-navbar->getDefFavBarHeight());
+ notify_view_rect.mTop += pm*(navbar->getDefNavBarHeight()-navbar->getDefFavBarHeight());
+ gFloaterView->setRect(floater_view_rect);
+ floater_view_rect = gFloaterView->getRect();
+ navbar->showNavigationPanel(newvalue.asBoolean());
return true;
}
bool toggle_show_favorites_panel(const LLSD& newvalue)
{
- LLNavigationBar::getInstance()->showFavoritesPanel(newvalue.asBoolean());
+ LLRect floater_view_rect = gFloaterView->getRect();
+ LLRect notify_view_rect = gNotifyBoxView->getRect();
+ LLNavigationBar* navbar = LLNavigationBar::getInstance();
+
+ //if newvalue contains 0 => favbar should turn invisible, so floater_view_rect should get higher,
+ //and to do this pm=1, else if favbar becomes visible pm=-1 so floater_view_rect gets lower.
+ int pm=newvalue.asBoolean()?-1:1;
+ floater_view_rect.mTop += pm*navbar->getDefFavBarHeight();
+ notify_view_rect.mTop += pm*navbar->getDefFavBarHeight();
+ gFloaterView->setRect(floater_view_rect);
+ navbar->showFavoritesPanel(newvalue.asBoolean());
return true;
}
diff --git a/indra/newview/llviewercontrol.h b/indra/newview/llviewercontrol.h
index b1f14eca7b..9b4e80cae0 100644
--- a/indra/newview/llviewercontrol.h
+++ b/indra/newview/llviewercontrol.h
@@ -43,6 +43,9 @@
extern BOOL gHackGodmode;
#endif
+bool toggle_show_navigation_panel(const LLSD& newvalue);
+bool toggle_show_favorites_panel(const LLSD& newvalue);
+
// These functions found in llcontroldef.cpp *TODO: clean this up!
//setting variables are declared in this function
void settings_setup_listeners();
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 57a4117d5d..366e5602bd 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -42,7 +42,6 @@
#include "llconsole.h"
#include "llinventorymodel.h"
#include "llnotify.h"
-#include "llimview.h"
#include "llgesturemgr.h"
#include "llinventorybridge.h"
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 41a676dc53..8bd74dcb04 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -156,10 +156,10 @@ public:
{
if(!mInitialized && ! mime_type.empty())
{
- if (mMediaImpl->initializeMedia(mime_type))
+ if(mMediaImpl->initializeMedia(mime_type))
{
mInitialized = true;
- mMediaImpl->play();
+ mMediaImpl->loadURI();
}
}
}
@@ -267,10 +267,6 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s
{
needs_navigate = (media_entry->getCurrentURL() != previous_url);
}
- else if(!media_entry->getHomeURL().empty())
- {
- needs_navigate = (media_entry->getHomeURL() != previous_url);
- }
}
}
else
@@ -293,8 +289,6 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s
if(media_impl && needs_navigate)
{
std::string url = media_entry->getCurrentURL();
- if(url.empty())
- url = media_entry->getHomeURL();
media_impl->navigateTo(url, "", true, true);
}
@@ -639,13 +633,14 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id,
mUsedInUI(false),
mHasFocus(false),
mPriority(LLPluginClassMedia::PRIORITY_UNLOADED),
- mDoNavigateOnLoad(false),
- mDoNavigateOnLoadRediscoverType(false),
- mDoNavigateOnLoadServerRequest(false),
+ mNavigateRediscoverType(false),
+ mNavigateServerRequest(false),
mMediaSourceFailed(false),
mRequestedVolume(1.0f),
mIsMuted(false),
mNeedsMuteCheck(false),
+ mPreviousMediaState(MEDIA_NONE),
+ mPreviousMediaTime(0.0f),
mIsUpdated(false)
{
@@ -716,7 +711,6 @@ bool LLViewerMediaImpl::initializeMedia(const std::string& mime_type)
mMimeType = mime_type;
}
- // play();
return (mMediaSource != NULL);
}
@@ -729,16 +723,13 @@ void LLViewerMediaImpl::createMediaSource()
return;
}
- if(mDoNavigateOnLoad)
+ if(! mMediaURL.empty())
{
- if(! mMediaURL.empty())
- {
- navigateTo(mMediaURL, mMimeType, mDoNavigateOnLoadRediscoverType, mDoNavigateOnLoadServerRequest);
- }
- else if(! mMimeType.empty())
- {
- initializeMedia(mMimeType);
- }
+ navigateInternal();
+ }
+ else if(! mMimeType.empty())
+ {
+ initializeMedia(mMimeType);
}
}
@@ -869,6 +860,46 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
return false;
}
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::loadURI()
+{
+ if(mMediaSource)
+ {
+ mMediaSource->loadURI( mMediaURL );
+
+ if(mPreviousMediaState == MEDIA_PLAYING)
+ {
+ // This media was playing before this instance was unloaded.
+
+ if(mPreviousMediaTime != 0.0f)
+ {
+ // Seek back to where we left off, if possible.
+ seek(mPreviousMediaTime);
+ }
+
+ start();
+ }
+ else if(mPreviousMediaState == MEDIA_PAUSED)
+ {
+ // This media was paused before this instance was unloaded.
+
+ if(mPreviousMediaTime != 0.0f)
+ {
+ // Seek back to where we left off, if possible.
+ seek(mPreviousMediaTime);
+ }
+
+ pause();
+ }
+ else
+ {
+ // No relevant previous media play state -- if we're loading the URL, we want to start playing.
+ start();
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
void LLViewerMediaImpl::setSize(int width, int height)
{
mMediaWidth = width;
@@ -882,24 +913,21 @@ void LLViewerMediaImpl::setSize(int width, int height)
//////////////////////////////////////////////////////////////////////////////////////////
void LLViewerMediaImpl::play()
{
- // first stop any previously playing media
- // stop();
-
- // mMediaSource->addObserver( this );
+ // If the media source isn't there, try to initialize it and load an URL.
if(mMediaSource == NULL)
{
- if(!initializePlugin(mMimeType))
+ if(!initializeMedia(mMimeType))
{
// This may be the case where the plugin's priority is PRIORITY_UNLOADED
return;
}
+
+ // Only do this if the media source was just loaded.
+ loadURI();
}
- mMediaSource->loadURI( mMediaURL );
- if(/*mMediaSource->pluginSupportsMediaTime()*/ true)
- {
- start();
- }
+ // always start the media
+ start();
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -1165,27 +1193,21 @@ void LLViewerMediaImpl::navigateHome()
//////////////////////////////////////////////////////////////////////////////////////////
void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type, bool rediscover_type, bool server_request)
{
- if(server_request)
- {
- setNavState(MEDIANAVSTATE_SERVER_SENT);
- }
- else
+ if(mMediaURL != url)
{
- setNavState(MEDIANAVSTATE_NONE);
+ // Don't carry media play state across distinct URLs.
+ resetPreviousMediaState();
}
// Always set the current URL and MIME type.
mMediaURL = url;
mMimeType = mime_type;
- // If the current URL is not null, make the instance do a navigate on load.
- mDoNavigateOnLoad = !mMediaURL.empty();
-
// if mime type discovery was requested, we'll need to do it when the media loads
- mDoNavigateOnLoadRediscoverType = rediscover_type;
+ mNavigateRediscoverType = rediscover_type;
// and if this was a server request, the navigate on load will also need to be one.
- mDoNavigateOnLoadServerRequest = server_request;
+ mNavigateServerRequest = server_request;
// An explicit navigate resets the "failed" flag.
mMediaSourceFailed = false;
@@ -1193,7 +1215,7 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi
if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED)
{
// Helpful to have media urls in log file. Shouldn't be spammy.
- llinfos << "UNLOADED media id= " << mTextureId << " url=" << url << " mime_type=" << mime_type << llendl;
+ llinfos << "NOT LOADING media id= " << mTextureId << " url=" << url << " mime_type=" << mime_type << llendl;
// This impl should not be loaded at this time.
LL_DEBUGS("PluginPriority") << this << "Not loading (PRIORITY_UNLOADED)" << LL_ENDL;
@@ -1201,10 +1223,24 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi
return;
}
+ navigateInternal();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::navigateInternal()
+{
// Helpful to have media urls in log file. Shouldn't be spammy.
- llinfos << "media id= " << mTextureId << " url=" << url << " mime_type=" << mime_type << llendl;
-
-
+ llinfos << "media id= " << mTextureId << " url=" << mMediaURL << " mime_type=" << mMimeType << llendl;
+
+ if(mNavigateServerRequest)
+ {
+ setNavState(MEDIANAVSTATE_SERVER_SENT);
+ }
+ else
+ {
+ setNavState(MEDIANAVSTATE_NONE);
+ }
+
// If the caller has specified a non-empty MIME type, look that up in our MIME types list.
// If we have a plugin for that MIME type, use that instead of attempting auto-discovery.
// This helps in supporting legacy media content where the server the media resides on returns a bogus MIME type
@@ -1216,11 +1252,11 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi
if(!plugin_basename.empty())
{
// We have a plugin for this mime type
- rediscover_type = false;
+ mNavigateRediscoverType = false;
}
}
- if(rediscover_type)
+ if(mNavigateRediscoverType)
{
LLURI uri(mMediaURL);
@@ -1236,7 +1272,7 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi
// We use "data" internally for a text/html url for loading the login screen
if(initializeMedia("text/html"))
{
- mMediaSource->loadURI( mMediaURL );
+ loadURI();
}
}
else
@@ -1244,24 +1280,18 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi
// This catches 'rtsp://' urls
if(initializeMedia(scheme))
{
- mMediaSource->loadURI( mMediaURL );
+ loadURI();
}
}
}
- else if (mMediaSource)
+ else if(initializeMedia(mMimeType))
{
- mMediaSource->loadURI( mMediaURL );
- }
- else if(initializeMedia(mime_type) && mMediaSource)
- {
- mMediaSource->loadURI( mMediaURL );
+ loadURI();
}
else
{
- LL_WARNS("Media") << "Couldn't navigate to: " << url << " as there is no media type for: " << mime_type << LL_ENDL;
- return;
+ LL_WARNS("Media") << "Couldn't navigate to: " << mMediaURL << " as there is no media type for: " << mMimeType << LL_ENDL;
}
-
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -1312,6 +1342,8 @@ bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask)
if(!result)
{
result = mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_DOWN ,key, mask);
+ // Since the viewer internal event dispatching doesn't give us key-up events, simulate one here.
+ (void)mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_UP ,key, mask);
}
}
@@ -1388,6 +1420,7 @@ void LLViewerMediaImpl::update()
if(mMediaSource->isPluginExited())
{
+ resetPreviousMediaState();
destroyMediaSource();
return;
}
@@ -1584,6 +1617,14 @@ bool LLViewerMediaImpl::hasMedia()
}
//////////////////////////////////////////////////////////////////////////////////////////
+//
+void LLViewerMediaImpl::resetPreviousMediaState()
+{
+ mPreviousMediaState = MEDIA_NONE;
+ mPreviousMediaTime = 0.0f;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginClassMediaOwner::EMediaEvent event)
{
switch(event)
@@ -1593,6 +1634,9 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
// The plugin failed to load properly. Make sure the timer doesn't retry.
// TODO: maybe mark this plugin as not loadable somehow?
mMediaSourceFailed = true;
+
+ // Reset the last known state of the media to defaults.
+ resetPreviousMediaState();
// TODO: may want a different message for this case?
LLSD args;
@@ -1606,6 +1650,9 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
// The plugin crashed.
mMediaSourceFailed = true;
+ // Reset the last known state of the media to defaults.
+ resetPreviousMediaState();
+
LLSD args;
args["PLUGIN"] = LLMIMETypes::implType(mMimeType);
// SJB: This is getting called every frame if the plugin fails to load, continuously respawining the alert!
@@ -1831,11 +1878,11 @@ void LLViewerMediaImpl::setUsedInUI(bool used_in_ui)
{
if(getVisible())
{
- mPriority = LLPluginClassMedia::PRIORITY_NORMAL;
+ setPriority(LLPluginClassMedia::PRIORITY_NORMAL);
}
else
{
- mPriority = LLPluginClassMedia::PRIORITY_HIDDEN;
+ setPriority(LLPluginClassMedia::PRIORITY_HIDDEN);
}
createMediaSource();
@@ -1856,6 +1903,15 @@ F64 LLViewerMediaImpl::getCPUUsage() const
void LLViewerMediaImpl::setPriority(LLPluginClassMedia::EPriority priority)
{
+ if(mPriority != priority)
+ {
+ LL_INFOS("PluginPriority")
+ << "changing priority of media id " << mTextureId
+ << " from " << LLPluginClassMedia::priorityToString(mPriority)
+ << " to " << LLPluginClassMedia::priorityToString(priority)
+ << LL_ENDL;
+ }
+
mPriority = priority;
if(priority == LLPluginClassMedia::PRIORITY_UNLOADED)
@@ -1863,6 +1919,11 @@ void LLViewerMediaImpl::setPriority(LLPluginClassMedia::EPriority priority)
if(mMediaSource)
{
// Need to unload the media source
+
+ // First, save off previous media state
+ mPreviousMediaState = mMediaSource->getStatus();
+ mPreviousMediaTime = mMediaSource->getCurrentTime();
+
destroyMediaSource();
}
}
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index b15314e954..4f0d39dd80 100644
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -123,6 +123,7 @@ public:
void setMediaType(const std::string& media_type);
bool initializeMedia(const std::string& mime_type);
bool initializePlugin(const std::string& media_type);
+ void loadURI();
LLPluginClassMedia* getMediaPlugin() { return mMediaSource; }
void setSize(int width, int height);
@@ -151,6 +152,7 @@ public:
void navigateReload();
void navigateHome();
void navigateTo(const std::string& url, const std::string& mime_type = "", bool rediscover_type = false, bool server_request = false);
+ void navigateInternal();
void navigateStop();
bool handleKeyHere(KEY key, MASK mask);
bool handleUnicodeCharHere(llwchar uni_char);
@@ -174,6 +176,7 @@ public:
bool isMediaPaused();
bool hasMedia();
bool isMediaFailed() { return mMediaSourceFailed; };
+ void resetPreviousMediaState();
ECursorType getLastSetCursor() { return mLastSetCursor; };
@@ -287,14 +290,14 @@ public:
bool mUsedInUI;
bool mHasFocus;
LLPluginClassMedia::EPriority mPriority;
- bool mDoNavigateOnLoad;
- bool mDoNavigateOnLoadRediscoverType;
- bool mDoNavigateOnLoadServerRequest;
+ bool mNavigateRediscoverType;
+ bool mNavigateServerRequest;
bool mMediaSourceFailed;
F32 mRequestedVolume;
bool mIsMuted;
bool mNeedsMuteCheck;
-
+ int mPreviousMediaState;
+ F64 mPreviousMediaTime;
private:
BOOL mIsUpdated ;
diff --git a/indra/newview/llviewermediafocus.cpp b/indra/newview/llviewermediafocus.cpp
index ad48ec145b..5d0b77d4fb 100644
--- a/indra/newview/llviewermediafocus.cpp
+++ b/indra/newview/llviewermediafocus.cpp
@@ -35,7 +35,7 @@
//LLViewerMediaFocus
#include "llviewerobjectlist.h"
-#include "llpanelmediahud.h"
+#include "llpanelprimmediacontrols.h"
#include "llpluginclassmedia.h"
#include "llagent.h"
#include "lltoolpie.h"
@@ -106,19 +106,19 @@ void LLViewerMediaFocus::setFocusFace(LLPointer<LLViewerObject> objectp, S32 fac
// We must do this before processing the media HUD zoom, or it may zoom to the wrong face.
update();
- if(mMediaHUD.get() && face_auto_zoom && ! parcel->getMediaPreventCameraZoom())
+ if(mMediaControls.get() && face_auto_zoom && ! parcel->getMediaPreventCameraZoom())
{
- mMediaHUD.get()->resetZoomLevel();
- mMediaHUD.get()->nextZoomLevel();
+ mMediaControls.get()->resetZoomLevel();
+ mMediaControls.get()->nextZoomLevel();
}
}
else
{
- if(hasFocus())
+ if(mFocusedImplID != LLUUID::null)
{
- if(mMediaHUD.get())
+ if(mMediaControls.get())
{
- mMediaHUD.get()->resetZoomLevel();
+ mMediaControls.get()->resetZoomLevel();
}
gFocusMgr.setKeyboardFocus(NULL);
@@ -249,20 +249,18 @@ void LLViewerMediaFocus::setCameraZoom(LLViewerObject* object, LLVector3 normal,
}
void LLViewerMediaFocus::onFocusReceived()
{
- // Don't do this here -- this doesn't change "inworld media focus", it just changes whether the viewer's input is focused on the media.
-// LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
-// if(media_impl.notNull())
-// media_impl->focus(true);
+ LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
+ if(media_impl)
+ media_impl->focus(true);
LLFocusableElement::onFocusReceived();
}
void LLViewerMediaFocus::onFocusLost()
{
- // Don't do this here -- this doesn't change "inworld media focus", it just changes whether the viewer's input is focused on the media.
-// LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
-// if(media_impl.notNull())
-// media_impl->focus(false);
+ LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
+ if(media_impl)
+ media_impl->focus(false);
gViewerWindow->focusClient();
LLFocusableElement::onFocusLost();
@@ -329,20 +327,20 @@ void LLViewerMediaFocus::update()
// We have an object and impl to point at.
// Make sure the media HUD object exists.
- if(! mMediaHUD.get())
+ if(! mMediaControls.get())
{
- LLPanelMediaHUD* media_hud = new LLPanelMediaHUD();
- mMediaHUD = media_hud->getHandle();
- gHUDView->addChild(media_hud);
+ LLPanelPrimMediaControls* media_controls = new LLPanelPrimMediaControls();
+ mMediaControls = media_controls->getHandle();
+ gHUDView->addChild(media_controls);
}
- mMediaHUD.get()->setMediaFace(viewer_object, face, media_impl, normal);
+ mMediaControls.get()->setMediaFace(viewer_object, face, media_impl, normal);
}
else
{
// The media HUD is no longer needed.
- if(mMediaHUD.get())
+ if(mMediaControls.get())
{
- mMediaHUD.get()->setMediaFace(NULL, 0, NULL);
+ mMediaControls.get()->setMediaFace(NULL, 0, NULL);
}
}
}
diff --git a/indra/newview/llviewermediafocus.h b/indra/newview/llviewermediafocus.h
index c77533ba5a..c1179de39d 100644
--- a/indra/newview/llviewermediafocus.h
+++ b/indra/newview/llviewermediafocus.h
@@ -40,7 +40,7 @@
#include "llselectmgr.h"
class LLViewerMediaImpl;
-class LLPanelMediaHUD;
+class LLPanelPrimMediaControls;
class LLViewerMediaFocus :
public LLFocusableElement,
@@ -88,7 +88,7 @@ protected:
private:
- LLHandle<LLPanelMediaHUD> mMediaHUD;
+ LLHandle<LLPanelPrimMediaControls> mMediaControls;
LLUUID mFocusedObjectID;
S32 mFocusedObjectFace;
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 058f44ef57..864cf9d57b 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -3483,7 +3483,6 @@ void set_god_level(U8 god_level)
{
U8 old_god_level = gAgent.getGodLevel();
gAgent.setGodLevel( god_level );
- gIMMgr->refresh();
LLViewerParcelMgr::getInstance()->notifyObservers();
// God mode changes sim visibility
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 791ec07349..ec6ef92a54 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -72,7 +72,6 @@
#include "llviewercontrol.h"
#include "lldrawpool.h"
#include "llfirstuse.h"
-#include "llfloateractivespeakers.h"
#include "llfloateranimpreview.h"
#include "llfloaterbuycurrency.h"
#include "llfloaterbuyland.h"
@@ -89,7 +88,6 @@
#include "llhudeffect.h"
#include "llhudeffecttrail.h"
#include "llhudmanager.h"
-#include "llimpanel.h"
#include "llinventorymodel.h"
#include "llfloaterinventory.h"
#include "llmenugl.h"
@@ -5680,7 +5678,7 @@ void onCovenantLoadComplete(LLVFS *vfs,
LLPanelLandCovenant::updateCovenantText(covenant_text);
LLFloaterBuyLand::updateCovenantText(covenant_text, asset_uuid);
- LLPanelPlaceInfo* panel = dynamic_cast<LLPanelPlaceInfo*>(LLSideTray::getInstance()->showPanel("panel_place_info", LLSD()));
+ LLPanelPlaceInfo* panel = LLSideTray::getInstance()->findChild<LLPanelPlaceInfo>("panel_place_info");
if (panel)
{
panel->updateCovenantText(covenant_text);
diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp
index 65994dfb30..5c40f2a540 100644
--- a/indra/newview/llviewertexteditor.cpp
+++ b/indra/newview/llviewertexteditor.cpp
@@ -44,6 +44,9 @@
#include "llinventory.h"
#include "llinventorybridge.h"
#include "llinventorymodel.h"
+#include "lllandmark.h"
+#include "lllandmarkactions.h"
+#include "lllandmarklist.h"
#include "llmemorystream.h"
#include "llmenugl.h"
#include "llnotecard.h"
@@ -64,10 +67,47 @@
#include "llviewertexturelist.h"
#include "llviewerwindow.h"
-#include "llappviewer.h" // for gPacificDaylightTime
-
static LLDefaultChildRegistry::Register<LLViewerTextEditor> r("text_editor");
+///-----------------------------------------------------------------------
+/// Class LLEmbeddedLandmarkCopied
+///-----------------------------------------------------------------------
+class LLEmbeddedLandmarkCopied: public LLInventoryCallback
+{
+public:
+
+ LLEmbeddedLandmarkCopied(){}
+ void fire(const LLUUID& inv_item)
+ {
+ showInfo(inv_item);
+ }
+ static void showInfo(const LLUUID& landmark_inv_id)
+ {
+ LLSD key;
+ key["type"] = "landmark";
+ key["id"] = landmark_inv_id;
+ LLSideTray::getInstance()->showPanel("panel_places", key);
+ }
+ static void processForeignLandmark(LLLandmark* landmark,
+ const LLUUID& object_id, const LLUUID& notecard_inventory_id,
+ LLInventoryItem* item)
+ {
+ LLVector3d global_pos;
+ landmark->getGlobalPos(global_pos);
+ LLViewerInventoryItem* agent_lanmark =
+ LLLandmarkActions::findLandmarkForGlobalPos(global_pos);
+
+ if (agent_lanmark)
+ {
+ showInfo(agent_lanmark->getUUID());
+ }
+ else
+ {
+ LLPointer<LLEmbeddedLandmarkCopied> cb = new LLEmbeddedLandmarkCopied();
+ copy_inventory_from_notecard(object_id, notecard_inventory_id, item, gInventoryCallbacks.registerCB(cb));
+ }
+ }
+};
///----------------------------------------------------------------------------
/// Class LLEmbeddedNotecardOpener
///----------------------------------------------------------------------------
@@ -1099,14 +1139,12 @@ void LLViewerTextEditor::openEmbeddedLandmark( LLInventoryItem* item, llwchar wc
if (!item)
return;
- LLSD key;
- key["type"] = "landmark";
- key["id"] = item->getUUID();
-
- LLPanelPlaces *panel = dynamic_cast<LLPanelPlaces*>(LLSideTray::getInstance()->showPanel("panel_places", key));
- if (panel)
+ LLLandmark* landmark = gLandmarkList.getAsset(item->getAssetUUID(),
+ boost::bind(&LLEmbeddedLandmarkCopied::processForeignLandmark, _1, mObjectID, mNotecardInventoryID, item));
+ if (landmark)
{
- panel->setItem(item);
+ LLEmbeddedLandmarkCopied::processForeignLandmark(landmark, mObjectID,
+ mNotecardInventoryID, item);
}
}
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index c659e58e47..ba32e07464 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -142,7 +142,6 @@
#include "llstatview.h"
#include "llsurface.h"
#include "llsurfacepatch.h"
-#include "llimview.h"
#include "lltexlayer.h"
#include "lltextbox.h"
#include "lltexturecache.h"
@@ -1519,11 +1518,12 @@ void LLViewerWindow::initWorldUI()
getRootView()->addChild(gMorphView);
// Make space for nav bar.
+ LLNavigationBar* navbar = LLNavigationBar::getInstance();
LLRect floater_view_rect = gFloaterView->getRect();
LLRect notify_view_rect = gNotifyBoxView->getRect();
- floater_view_rect.mTop -= NAVIGATION_BAR_HEIGHT;
+ floater_view_rect.mTop -= navbar->getDefNavBarHeight();
floater_view_rect.mBottom += LLBottomTray::getInstance()->getRect().getHeight();
- notify_view_rect.mTop -= NAVIGATION_BAR_HEIGHT;
+ notify_view_rect.mTop -= navbar->getDefNavBarHeight();
notify_view_rect.mBottom += LLBottomTray::getInstance()->getRect().getHeight();
gFloaterView->setRect(floater_view_rect);
gNotifyBoxView->setRect(notify_view_rect);
@@ -1550,20 +1550,19 @@ void LLViewerWindow::initWorldUI()
gStatusBar->setBackgroundColor( gMenuBarView->getBackgroundColor().get() );
// Navigation bar
-
- LLNavigationBar* navbar = LLNavigationBar::getInstance();
navbar->reshape(root_rect.getWidth(), navbar->getRect().getHeight(), TRUE); // *TODO: redundant?
navbar->translate(0, root_rect.getHeight() - menu_bar_height - navbar->getRect().getHeight()); // FIXME
navbar->setBackgroundColor(gMenuBarView->getBackgroundColor().get());
+
if (!gSavedSettings.getBOOL("ShowNavbarNavigationPanel"))
{
- navbar->showNavigationPanel(FALSE);
+ toggle_show_navigation_panel(LLSD(0));
}
if (!gSavedSettings.getBOOL("ShowNavbarFavoritesPanel"))
{
- navbar->showFavoritesPanel(FALSE);
+ toggle_show_favorites_panel(LLSD(0));
}
if (!gSavedSettings.getBOOL("ShowCameraButton"))
@@ -1637,7 +1636,11 @@ void LLViewerWindow::shutdownViews()
// DEV-40930: Clear sModalStack. Otherwise, any LLModalDialog left open
// will crump with LL_ERRS.
LLModalDialog::shutdownModals();
-
+
+ // destroy the nav bar, not currently part of gViewerWindow
+ // *TODO: Make LLNavigationBar part of gViewerWindow
+ delete LLNavigationBar::getInstance();
+
// Delete all child views.
delete mRootView;
mRootView = NULL;
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index a402aff8ab..4bf66ba17e 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -2448,28 +2448,20 @@ void LLVOAvatar::idleUpdateAppearanceAnimation()
}
else
{
- F32 blend_frac = calc_bouncy_animation(appearance_anim_time / APPEARANCE_MORPH_TIME);
- F32 last_blend_frac = calc_bouncy_animation(mLastAppearanceBlendTime / APPEARANCE_MORPH_TIME);
- F32 morph_amt;
- if (last_blend_frac == 1.f)
- {
- morph_amt = 1.f;
- }
- else
- {
- morph_amt = (blend_frac - last_blend_frac) / (1.f - last_blend_frac);
- }
-
+ F32 morph_amt = calcMorphAmount();
LLVisualParam *param;
- // animate only top level params
- for (param = getFirstVisualParam();
- param;
- param = getNextVisualParam())
+ if (!isSelf())
{
- if (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE)
+ // animate only top level params for non-self avatars
+ for (param = getFirstVisualParam();
+ param;
+ param = getNextVisualParam())
{
- param->animate(morph_amt, mAppearanceAnimSetByUser);
+ if (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE)
+ {
+ param->animate(morph_amt, mAppearanceAnimSetByUser);
+ }
}
}
@@ -2487,6 +2479,25 @@ void LLVOAvatar::idleUpdateAppearanceAnimation()
}
}
+F32 LLVOAvatar::calcMorphAmount()
+{
+ F32 appearance_anim_time = mAppearanceMorphTimer.getElapsedTimeF32();
+ F32 blend_frac = calc_bouncy_animation(appearance_anim_time / APPEARANCE_MORPH_TIME);
+ F32 last_blend_frac = calc_bouncy_animation(mLastAppearanceBlendTime / APPEARANCE_MORPH_TIME);
+
+ F32 morph_amt;
+ if (last_blend_frac == 1.f)
+ {
+ morph_amt = 1.f;
+ }
+ else
+ {
+ morph_amt = (blend_frac - last_blend_frac) / (1.f - last_blend_frac);
+ }
+
+ return morph_amt;
+}
+
void LLVOAvatar::idleUpdateLipSync(bool voice_enabled)
{
// Use the Lipsync_Ooh and Lipsync_Aah morphs for lip sync
@@ -6400,6 +6411,11 @@ LLBBox LLVOAvatar::getHUDBBox() const
++attachment_iter)
{
const LLViewerObject* attached_object = (*attachment_iter);
+ if (attached_object == NULL)
+ {
+ llwarns << "HUD attached object is NULL!" << llendl;
+ continue;
+ }
// initialize bounding box to contain identity orientation and center point for attached object
bbox.addPointLocal(attached_object->getPosition());
// add rotated bounding box for attached object
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index e3add8aa78..f7c794defe 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -205,7 +205,7 @@ public:
virtual BOOL updateCharacter(LLAgent &agent);
void idleUpdateVoiceVisualizer(bool voice_enabled);
void idleUpdateMisc(bool detailed_update);
- void idleUpdateAppearanceAnimation();
+ virtual void idleUpdateAppearanceAnimation();
void idleUpdateLipSync(bool voice_enabled);
void idleUpdateLoadingEffect();
void idleUpdateWindEffect();
@@ -250,6 +250,7 @@ protected:
virtual BOOL updateIsFullyLoaded();
BOOL processFullyLoadedChange(bool loading);
void updateRuthTimer(bool loading);
+ F32 calcMorphAmount();
private:
BOOL mFullyLoaded;
BOOL mPreviousFullyLoaded;
@@ -276,7 +277,7 @@ public:
protected:
static BOOL parseSkeletonFile(const std::string& filename);
void buildCharacter();
- BOOL loadAvatar();
+ virtual BOOL loadAvatar();
BOOL setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent, S32 &current_volume_num, S32 &current_joint_num);
BOOL buildSkeleton(const LLVOAvatarSkeletonInfo *info);
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 4760d5a472..758db538a2 100644
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -193,6 +193,25 @@ void LLVOAvatarSelf::markDead()
LLVOAvatar::markDead();
}
+/*virtual*/ BOOL LLVOAvatarSelf::loadAvatar()
+{
+ BOOL success = LLVOAvatar::loadAvatar();
+
+ // set all parameters sotred directly in the avatar to have
+ // the isSelfParam to be TRUE - this is used to prevent
+ // them from being animated or trigger accidental rebakes
+ // when we copy params from the wearable to the base avatar.
+ for (LLViewerVisualParam* param = (LLViewerVisualParam*) getFirstVisualParam();
+ param;
+ param = (LLViewerVisualParam*) getNextVisualParam())
+ {
+ param->setIsDummy(TRUE);
+ }
+
+ return success;
+}
+
+
BOOL LLVOAvatarSelf::loadAvatarSelf()
{
BOOL success = TRUE;
@@ -704,16 +723,23 @@ void LLVOAvatarSelf::updateVisualParams()
}
}
- LLWearable *shape = gAgentWearables.getWearable(WT_SHAPE,0);
- if (shape)
- {
- F32 gender = shape->getVisualParamWeight(80); // param 80 == gender
- setVisualParamWeight("male",gender ,TRUE);
- }
-
LLVOAvatar::updateVisualParams();
}
+/*virtual*/
+void LLVOAvatarSelf::idleUpdateAppearanceAnimation()
+{
+ // Animate all top-level wearable visual parameters
+ gAgentWearables.animateAllWearableParams(calcMorphAmount(), mAppearanceAnimSetByUser);
+
+ // apply wearable visual params to avatar
+ updateVisualParams();
+
+ //allow avatar to process updates
+ LLVOAvatar::idleUpdateAppearanceAnimation();
+
+}
+
// virtual
void LLVOAvatarSelf::requestStopMotion(LLMotion* motion)
{
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
index a555d04a63..6e52b33634 100644
--- a/indra/newview/llvoavatarself.h
+++ b/indra/newview/llvoavatarself.h
@@ -57,6 +57,7 @@ public:
virtual void markDead();
virtual void initInstance(); // Called after construction to initialize the class.
protected:
+ /*virtual*/ BOOL loadAvatar();
BOOL loadAvatarSelf();
BOOL buildSkeletonSelf(const LLVOAvatarSkeletonInfo *info);
BOOL buildMenus();
@@ -89,6 +90,7 @@ public:
/*virtual*/ BOOL setVisualParamWeight(const char* param_name, F32 weight, BOOL set_by_user = FALSE );
/*virtual*/ BOOL setVisualParamWeight(S32 index, F32 weight, BOOL set_by_user = FALSE );
/*virtual*/ void updateVisualParams();
+ /*virtual*/ void idleUpdateAppearanceAnimation();
private:
// helper function. Passed in param is assumed to be in avatar's parameter list.
diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp
new file mode 100644
index 0000000000..96fcf61e62
--- /dev/null
+++ b/indra/newview/llvoicechannel.cpp
@@ -0,0 +1,872 @@
+/**
+ * @file llvoicechannel.cpp
+ * @brief Voice Channel related classes
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-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 "llagent.h"
+#include "llfloaterreg.h"
+#include "llimview.h"
+#include "llnotifications.h"
+#include "llpanel.h"
+#include "llrecentpeople.h"
+#include "llviewercontrol.h"
+#include "llvoicechannel.h"
+
+
+LLVoiceChannel::voice_channel_map_t LLVoiceChannel::sVoiceChannelMap;
+LLVoiceChannel::voice_channel_map_uri_t LLVoiceChannel::sVoiceChannelURIMap;
+LLVoiceChannel* LLVoiceChannel::sCurrentVoiceChannel = NULL;
+LLVoiceChannel* LLVoiceChannel::sSuspendedVoiceChannel = NULL;
+
+BOOL LLVoiceChannel::sSuspended = FALSE;
+
+//
+// Constants
+//
+const U32 DEFAULT_RETRIES_COUNT = 3;
+
+
+class LLVoiceCallCapResponder : public LLHTTPClient::Responder
+{
+public:
+ LLVoiceCallCapResponder(const LLUUID& session_id) : mSessionID(session_id) {};
+
+ virtual void error(U32 status, const std::string& reason); // called with bad status codes
+ virtual void result(const LLSD& content);
+
+private:
+ LLUUID mSessionID;
+};
+
+
+void LLVoiceCallCapResponder::error(U32 status, const std::string& reason)
+{
+ llwarns << "LLVoiceCallCapResponder::error("
+ << status << ": " << reason << ")"
+ << llendl;
+ LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID);
+ if ( channelp )
+ {
+ if ( 403 == status )
+ {
+ //403 == no ability
+ LLNotifications::instance().add(
+ "VoiceNotAllowed",
+ channelp->getNotifyArgs());
+ }
+ else
+ {
+ LLNotifications::instance().add(
+ "VoiceCallGenericError",
+ channelp->getNotifyArgs());
+ }
+ channelp->deactivate();
+ }
+}
+
+void LLVoiceCallCapResponder::result(const LLSD& content)
+{
+ LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(mSessionID);
+ if (channelp)
+ {
+ //*TODO: DEBUG SPAM
+ LLSD::map_const_iterator iter;
+ for(iter = content.beginMap(); iter != content.endMap(); ++iter)
+ {
+ llinfos << "LLVoiceCallCapResponder::result got "
+ << iter->first << llendl;
+ }
+
+ channelp->setChannelInfo(
+ content["voice_credentials"]["channel_uri"].asString(),
+ content["voice_credentials"]["channel_credentials"].asString());
+ }
+}
+
+//
+// LLVoiceChannel
+//
+LLVoiceChannel::LLVoiceChannel(const LLUUID& session_id, const std::string& session_name) :
+ mSessionID(session_id),
+ mState(STATE_NO_CHANNEL_INFO),
+ mSessionName(session_name),
+ mIgnoreNextSessionLeave(FALSE)
+{
+ mNotifyArgs["VOICE_CHANNEL_NAME"] = mSessionName;
+
+ if (!sVoiceChannelMap.insert(std::make_pair(session_id, this)).second)
+ {
+ // a voice channel already exists for this session id, so this instance will be orphaned
+ // the end result should simply be the failure to make voice calls
+ llwarns << "Duplicate voice channels registered for session_id " << session_id << llendl;
+ }
+
+ LLVoiceClient::getInstance()->addObserver(this);
+}
+
+LLVoiceChannel::~LLVoiceChannel()
+{
+ // Don't use LLVoiceClient::getInstance() here -- this can get called during atexit() time and that singleton MAY have already been destroyed.
+ if(gVoiceClient)
+ {
+ gVoiceClient->removeObserver(this);
+ }
+
+ sVoiceChannelMap.erase(mSessionID);
+ sVoiceChannelURIMap.erase(mURI);
+}
+
+void LLVoiceChannel::setChannelInfo(
+ const std::string& uri,
+ const std::string& credentials)
+{
+ setURI(uri);
+
+ mCredentials = credentials;
+
+ if (mState == STATE_NO_CHANNEL_INFO)
+ {
+ if (mURI.empty())
+ {
+ LLNotifications::instance().add("VoiceChannelJoinFailed", mNotifyArgs);
+ llwarns << "Received empty URI for channel " << mSessionName << llendl;
+ deactivate();
+ }
+ else if (mCredentials.empty())
+ {
+ LLNotifications::instance().add("VoiceChannelJoinFailed", mNotifyArgs);
+ llwarns << "Received empty credentials for channel " << mSessionName << llendl;
+ deactivate();
+ }
+ else
+ {
+ setState(STATE_READY);
+
+ // if we are supposed to be active, reconnect
+ // this will happen on initial connect, as we request credentials on first use
+ if (sCurrentVoiceChannel == this)
+ {
+ // just in case we got new channel info while active
+ // should move over to new channel
+ activate();
+ }
+ }
+ }
+}
+
+void LLVoiceChannel::onChange(EStatusType type, const std::string &channelURI, bool proximal)
+{
+ if (channelURI != mURI)
+ {
+ return;
+ }
+
+ if (type < BEGIN_ERROR_STATUS)
+ {
+ handleStatusChange(type);
+ }
+ else
+ {
+ handleError(type);
+ }
+}
+
+void LLVoiceChannel::handleStatusChange(EStatusType type)
+{
+ // status updates
+ switch(type)
+ {
+ case STATUS_LOGIN_RETRY:
+ //mLoginNotificationHandle = LLNotifyBox::showXml("VoiceLoginRetry")->getHandle();
+ LLNotifications::instance().add("VoiceLoginRetry");
+ break;
+ case STATUS_LOGGED_IN:
+ //if (!mLoginNotificationHandle.isDead())
+ //{
+ // LLNotifyBox* notifyp = (LLNotifyBox*)mLoginNotificationHandle.get();
+ // if (notifyp)
+ // {
+ // notifyp->close();
+ // }
+ // mLoginNotificationHandle.markDead();
+ //}
+ break;
+ case STATUS_LEFT_CHANNEL:
+ if (callStarted() && !mIgnoreNextSessionLeave && !sSuspended)
+ {
+ // if forceably removed from channel
+ // update the UI and revert to default channel
+ LLNotifications::instance().add("VoiceChannelDisconnected", mNotifyArgs);
+ deactivate();
+ }
+ mIgnoreNextSessionLeave = FALSE;
+ break;
+ case STATUS_JOINING:
+ if (callStarted())
+ {
+ setState(STATE_RINGING);
+ }
+ break;
+ case STATUS_JOINED:
+ if (callStarted())
+ {
+ setState(STATE_CONNECTED);
+ }
+ default:
+ break;
+ }
+}
+
+// default behavior is to just deactivate channel
+// derived classes provide specific error messages
+void LLVoiceChannel::handleError(EStatusType type)
+{
+ deactivate();
+ setState(STATE_ERROR);
+}
+
+BOOL LLVoiceChannel::isActive()
+{
+ // only considered active when currently bound channel matches what our channel
+ return callStarted() && LLVoiceClient::getInstance()->getCurrentChannel() == mURI;
+}
+
+BOOL LLVoiceChannel::callStarted()
+{
+ return mState >= STATE_CALL_STARTED;
+}
+
+void LLVoiceChannel::deactivate()
+{
+ if (mState >= STATE_RINGING)
+ {
+ // ignore session leave event
+ mIgnoreNextSessionLeave = TRUE;
+ }
+
+ if (callStarted())
+ {
+ setState(STATE_HUNG_UP);
+ // mute the microphone if required when returning to the proximal channel
+ if (gSavedSettings.getBOOL("AutoDisengageMic") && sCurrentVoiceChannel == this)
+ {
+ gSavedSettings.setBOOL("PTTCurrentlyEnabled", true);
+ }
+ }
+
+ if (sCurrentVoiceChannel == this)
+ {
+ // default channel is proximal channel
+ sCurrentVoiceChannel = LLVoiceChannelProximal::getInstance();
+ sCurrentVoiceChannel->activate();
+ }
+}
+
+void LLVoiceChannel::activate()
+{
+ if (callStarted())
+ {
+ return;
+ }
+
+ // deactivate old channel and mark ourselves as the active one
+ if (sCurrentVoiceChannel != this)
+ {
+ // mark as current before deactivating the old channel to prevent
+ // activating the proximal channel between IM calls
+ LLVoiceChannel* old_channel = sCurrentVoiceChannel;
+ sCurrentVoiceChannel = this;
+ if (old_channel)
+ {
+ old_channel->deactivate();
+ }
+ }
+
+ if (mState == STATE_NO_CHANNEL_INFO)
+ {
+ // responsible for setting status to active
+ getChannelInfo();
+ }
+ else
+ {
+ setState(STATE_CALL_STARTED);
+ }
+}
+
+void LLVoiceChannel::getChannelInfo()
+{
+ // pretend we have everything we need
+ if (sCurrentVoiceChannel == this)
+ {
+ setState(STATE_CALL_STARTED);
+ }
+}
+
+//static
+LLVoiceChannel* LLVoiceChannel::getChannelByID(const LLUUID& session_id)
+{
+ voice_channel_map_t::iterator found_it = sVoiceChannelMap.find(session_id);
+ if (found_it == sVoiceChannelMap.end())
+ {
+ return NULL;
+ }
+ else
+ {
+ return found_it->second;
+ }
+}
+
+//static
+LLVoiceChannel* LLVoiceChannel::getChannelByURI(std::string uri)
+{
+ voice_channel_map_uri_t::iterator found_it = sVoiceChannelURIMap.find(uri);
+ if (found_it == sVoiceChannelURIMap.end())
+ {
+ return NULL;
+ }
+ else
+ {
+ return found_it->second;
+ }
+}
+
+void LLVoiceChannel::updateSessionID(const LLUUID& new_session_id)
+{
+ sVoiceChannelMap.erase(sVoiceChannelMap.find(mSessionID));
+ mSessionID = new_session_id;
+ sVoiceChannelMap.insert(std::make_pair(mSessionID, this));
+}
+
+void LLVoiceChannel::setURI(std::string uri)
+{
+ sVoiceChannelURIMap.erase(mURI);
+ mURI = uri;
+ sVoiceChannelURIMap.insert(std::make_pair(mURI, this));
+}
+
+void LLVoiceChannel::setState(EState state)
+{
+ switch(state)
+ {
+ case STATE_RINGING:
+ gIMMgr->addSystemMessage(mSessionID, "ringing", mNotifyArgs);
+ break;
+ case STATE_CONNECTED:
+ gIMMgr->addSystemMessage(mSessionID, "connected", mNotifyArgs);
+ break;
+ case STATE_HUNG_UP:
+ gIMMgr->addSystemMessage(mSessionID, "hang_up", mNotifyArgs);
+ break;
+ default:
+ break;
+ }
+
+ mState = state;
+}
+
+void LLVoiceChannel::toggleCallWindowIfNeeded(EState state)
+{
+ if (state == STATE_CONNECTED)
+ {
+ LLFloaterReg::showInstance("voice_call", mSessionID);
+ }
+ // By checking that current state is CONNECTED we make sure that the call window
+ // has been shown, hence there's something to hide. This helps when user presses
+ // the "End call" button right after initiating the call.
+ // *TODO: move this check to LLFloaterCall?
+ else if (state == STATE_HUNG_UP && mState == STATE_CONNECTED)
+ {
+ LLFloaterReg::hideInstance("voice_call", mSessionID);
+ }
+}
+
+//static
+void LLVoiceChannel::initClass()
+{
+ sCurrentVoiceChannel = LLVoiceChannelProximal::getInstance();
+}
+
+
+//static
+void LLVoiceChannel::suspend()
+{
+ if (!sSuspended)
+ {
+ sSuspendedVoiceChannel = sCurrentVoiceChannel;
+ sSuspended = TRUE;
+ }
+}
+
+//static
+void LLVoiceChannel::resume()
+{
+ if (sSuspended)
+ {
+ if (gVoiceClient->voiceEnabled())
+ {
+ if (sSuspendedVoiceChannel)
+ {
+ sSuspendedVoiceChannel->activate();
+ }
+ else
+ {
+ LLVoiceChannelProximal::getInstance()->activate();
+ }
+ }
+ sSuspended = FALSE;
+ }
+}
+
+
+//
+// LLVoiceChannelGroup
+//
+
+LLVoiceChannelGroup::LLVoiceChannelGroup(const LLUUID& session_id, const std::string& session_name) :
+ LLVoiceChannel(session_id, session_name)
+{
+ mRetries = DEFAULT_RETRIES_COUNT;
+ mIsRetrying = FALSE;
+}
+
+void LLVoiceChannelGroup::deactivate()
+{
+ if (callStarted())
+ {
+ LLVoiceClient::getInstance()->leaveNonSpatialChannel();
+ }
+ LLVoiceChannel::deactivate();
+}
+
+void LLVoiceChannelGroup::activate()
+{
+ if (callStarted()) return;
+
+ LLVoiceChannel::activate();
+
+ if (callStarted())
+ {
+ // we have the channel info, just need to use it now
+ LLVoiceClient::getInstance()->setNonSpatialChannel(
+ mURI,
+ mCredentials);
+
+#if 0 // *TODO
+ if (!gAgent.isInGroup(mSessionID)) // ad-hoc channel
+ {
+ // Add the party to the list of people with which we've recently interacted.
+ for (/*people in the chat*/)
+ LLRecentPeople::instance().add(buddy_id);
+ }
+#endif
+ }
+}
+
+void LLVoiceChannelGroup::getChannelInfo()
+{
+ LLViewerRegion* region = gAgent.getRegion();
+ if (region)
+ {
+ std::string url = region->getCapability("ChatSessionRequest");
+ LLSD data;
+ data["method"] = "call";
+ data["session-id"] = mSessionID;
+ LLHTTPClient::post(url,
+ data,
+ new LLVoiceCallCapResponder(mSessionID));
+ }
+}
+
+void LLVoiceChannelGroup::setChannelInfo(
+ const std::string& uri,
+ const std::string& credentials)
+{
+ setURI(uri);
+
+ mCredentials = credentials;
+
+ if (mState == STATE_NO_CHANNEL_INFO)
+ {
+ if(!mURI.empty() && !mCredentials.empty())
+ {
+ setState(STATE_READY);
+
+ // if we are supposed to be active, reconnect
+ // this will happen on initial connect, as we request credentials on first use
+ if (sCurrentVoiceChannel == this)
+ {
+ // just in case we got new channel info while active
+ // should move over to new channel
+ activate();
+ }
+ }
+ else
+ {
+ //*TODO: notify user
+ llwarns << "Received invalid credentials for channel " << mSessionName << llendl;
+ deactivate();
+ }
+ }
+ else if ( mIsRetrying )
+ {
+ // we have the channel info, just need to use it now
+ LLVoiceClient::getInstance()->setNonSpatialChannel(
+ mURI,
+ mCredentials);
+ }
+}
+
+void LLVoiceChannelGroup::handleStatusChange(EStatusType type)
+{
+ // status updates
+ switch(type)
+ {
+ case STATUS_JOINED:
+ mRetries = 3;
+ mIsRetrying = FALSE;
+ default:
+ break;
+ }
+
+ LLVoiceChannel::handleStatusChange(type);
+}
+
+void LLVoiceChannelGroup::handleError(EStatusType status)
+{
+ std::string notify;
+ switch(status)
+ {
+ case ERROR_CHANNEL_LOCKED:
+ case ERROR_CHANNEL_FULL:
+ notify = "VoiceChannelFull";
+ break;
+ case ERROR_NOT_AVAILABLE:
+ //clear URI and credentials
+ //set the state to be no info
+ //and activate
+ if ( mRetries > 0 )
+ {
+ mRetries--;
+ mIsRetrying = TRUE;
+ mIgnoreNextSessionLeave = TRUE;
+
+ getChannelInfo();
+ return;
+ }
+ else
+ {
+ notify = "VoiceChannelJoinFailed";
+ mRetries = DEFAULT_RETRIES_COUNT;
+ mIsRetrying = FALSE;
+ }
+
+ break;
+
+ case ERROR_UNKNOWN:
+ default:
+ break;
+ }
+
+ // notification
+ if (!notify.empty())
+ {
+ LLNotificationPtr notification = LLNotifications::instance().add(notify, mNotifyArgs);
+ // echo to im window
+ gIMMgr->addMessage(mSessionID, LLUUID::null, SYSTEM_FROM, notification->getMessage());
+ }
+
+ LLVoiceChannel::handleError(status);
+}
+
+void LLVoiceChannelGroup::setState(EState state)
+{
+ // HACK: Open/close the call window if needed.
+ toggleCallWindowIfNeeded(state);
+
+ switch(state)
+ {
+ case STATE_RINGING:
+ if ( !mIsRetrying )
+ {
+ gIMMgr->addSystemMessage(mSessionID, "ringing", mNotifyArgs);
+ }
+
+ mState = state;
+ break;
+ default:
+ LLVoiceChannel::setState(state);
+ }
+}
+
+//
+// LLVoiceChannelProximal
+//
+LLVoiceChannelProximal::LLVoiceChannelProximal() :
+ LLVoiceChannel(LLUUID::null, LLStringUtil::null)
+{
+ activate();
+}
+
+BOOL LLVoiceChannelProximal::isActive()
+{
+ return callStarted() && LLVoiceClient::getInstance()->inProximalChannel();
+}
+
+void LLVoiceChannelProximal::activate()
+{
+ if (callStarted()) return;
+
+ LLVoiceChannel::activate();
+
+ if (callStarted())
+ {
+ // this implicitly puts you back in the spatial channel
+ LLVoiceClient::getInstance()->leaveNonSpatialChannel();
+ }
+}
+
+void LLVoiceChannelProximal::onChange(EStatusType type, const std::string &channelURI, bool proximal)
+{
+ if (!proximal)
+ {
+ return;
+ }
+
+ if (type < BEGIN_ERROR_STATUS)
+ {
+ handleStatusChange(type);
+ }
+ else
+ {
+ handleError(type);
+ }
+}
+
+void LLVoiceChannelProximal::handleStatusChange(EStatusType status)
+{
+ // status updates
+ switch(status)
+ {
+ case STATUS_LEFT_CHANNEL:
+ // do not notify user when leaving proximal channel
+ return;
+ case STATUS_VOICE_DISABLED:
+ gIMMgr->addSystemMessage(LLUUID::null, "unavailable", mNotifyArgs);
+ return;
+ default:
+ break;
+ }
+ LLVoiceChannel::handleStatusChange(status);
+}
+
+
+void LLVoiceChannelProximal::handleError(EStatusType status)
+{
+ std::string notify;
+ switch(status)
+ {
+ case ERROR_CHANNEL_LOCKED:
+ case ERROR_CHANNEL_FULL:
+ notify = "ProximalVoiceChannelFull";
+ break;
+ default:
+ break;
+ }
+
+ // notification
+ if (!notify.empty())
+ {
+ LLNotifications::instance().add(notify, mNotifyArgs);
+ }
+
+ LLVoiceChannel::handleError(status);
+}
+
+void LLVoiceChannelProximal::deactivate()
+{
+ if (callStarted())
+ {
+ setState(STATE_HUNG_UP);
+ }
+}
+
+
+//
+// LLVoiceChannelP2P
+//
+LLVoiceChannelP2P::LLVoiceChannelP2P(const LLUUID& session_id, const std::string& session_name, const LLUUID& other_user_id) :
+ LLVoiceChannelGroup(session_id, session_name),
+ mOtherUserID(other_user_id),
+ mReceivedCall(FALSE)
+{
+ // make sure URI reflects encoded version of other user's agent id
+ setURI(LLVoiceClient::getInstance()->sipURIFromID(other_user_id));
+}
+
+void LLVoiceChannelP2P::handleStatusChange(EStatusType type)
+{
+ // status updates
+ switch(type)
+ {
+ case STATUS_LEFT_CHANNEL:
+ if (callStarted() && !mIgnoreNextSessionLeave && !sSuspended)
+ {
+ if (mState == STATE_RINGING)
+ {
+ // other user declined call
+ LLNotifications::instance().add("P2PCallDeclined", mNotifyArgs);
+ }
+ else
+ {
+ // other user hung up
+ LLNotifications::instance().add("VoiceChannelDisconnectedP2P", mNotifyArgs);
+ }
+ deactivate();
+ }
+ mIgnoreNextSessionLeave = FALSE;
+ return;
+ default:
+ break;
+ }
+
+ LLVoiceChannel::handleStatusChange(type);
+}
+
+void LLVoiceChannelP2P::handleError(EStatusType type)
+{
+ switch(type)
+ {
+ case ERROR_NOT_AVAILABLE:
+ LLNotifications::instance().add("P2PCallNoAnswer", mNotifyArgs);
+ break;
+ default:
+ break;
+ }
+
+ LLVoiceChannel::handleError(type);
+}
+
+void LLVoiceChannelP2P::activate()
+{
+ if (callStarted()) return;
+
+ LLVoiceChannel::activate();
+
+ if (callStarted())
+ {
+ // no session handle yet, we're starting the call
+ if (mSessionHandle.empty())
+ {
+ mReceivedCall = FALSE;
+ LLVoiceClient::getInstance()->callUser(mOtherUserID);
+ }
+ // otherwise answering the call
+ else
+ {
+ LLVoiceClient::getInstance()->answerInvite(mSessionHandle);
+
+ // using the session handle invalidates it. Clear it out here so we can't reuse it by accident.
+ mSessionHandle.clear();
+ }
+
+ // Add the party to the list of people with which we've recently interacted.
+ LLRecentPeople::instance().add(mOtherUserID);
+ }
+}
+
+void LLVoiceChannelP2P::getChannelInfo()
+{
+ // pretend we have everything we need, since P2P doesn't use channel info
+ if (sCurrentVoiceChannel == this)
+ {
+ setState(STATE_CALL_STARTED);
+ }
+}
+
+// receiving session from other user who initiated call
+void LLVoiceChannelP2P::setSessionHandle(const std::string& handle, const std::string &inURI)
+{
+ BOOL needs_activate = FALSE;
+ if (callStarted())
+ {
+ // defer to lower agent id when already active
+ if (mOtherUserID < gAgent.getID())
+ {
+ // pretend we haven't started the call yet, so we can connect to this session instead
+ deactivate();
+ needs_activate = TRUE;
+ }
+ else
+ {
+ // we are active and have priority, invite the other user again
+ // under the assumption they will join this new session
+ mSessionHandle.clear();
+ LLVoiceClient::getInstance()->callUser(mOtherUserID);
+ return;
+ }
+ }
+
+ mSessionHandle = handle;
+
+ // The URI of a p2p session should always be the other end's SIP URI.
+ if(!inURI.empty())
+ {
+ setURI(inURI);
+ }
+ else
+ {
+ setURI(LLVoiceClient::getInstance()->sipURIFromID(mOtherUserID));
+ }
+
+ mReceivedCall = TRUE;
+
+ if (needs_activate)
+ {
+ activate();
+ }
+}
+
+void LLVoiceChannelP2P::setState(EState state)
+{
+ // HACK: Open/close the call window if needed.
+ toggleCallWindowIfNeeded(state);
+
+ // you only "answer" voice invites in p2p mode
+ // so provide a special purpose message here
+ if (mReceivedCall && state == STATE_RINGING)
+ {
+ gIMMgr->addSystemMessage(mSessionID, "answering", mNotifyArgs);
+ mState = state;
+ return;
+ }
+ LLVoiceChannel::setState(state);
+}
diff --git a/indra/newview/llvoicechannel.h b/indra/newview/llvoicechannel.h
new file mode 100644
index 0000000000..9966bdd5ab
--- /dev/null
+++ b/indra/newview/llvoicechannel.h
@@ -0,0 +1,168 @@
+/**
+ * @file llvoicechannel.h
+ * @brief Voice channel related classes
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-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_VOICECHANNEL_H
+#define LL_VOICECHANNEL_H
+
+#include "llhandle.h"
+#include "llvoiceclient.h"
+
+class LLPanel;
+
+class LLVoiceChannel : public LLVoiceClientStatusObserver
+{
+public:
+ typedef enum e_voice_channel_state
+ {
+ STATE_NO_CHANNEL_INFO,
+ STATE_ERROR,
+ STATE_HUNG_UP,
+ STATE_READY,
+ STATE_CALL_STARTED,
+ STATE_RINGING,
+ STATE_CONNECTED
+ } EState;
+
+ LLVoiceChannel(const LLUUID& session_id, const std::string& session_name);
+ virtual ~LLVoiceChannel();
+
+ /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
+
+ virtual void handleStatusChange(EStatusType status);
+ virtual void handleError(EStatusType status);
+ virtual void deactivate();
+ virtual void activate();
+ virtual void setChannelInfo(
+ const std::string& uri,
+ const std::string& credentials);
+ virtual void getChannelInfo();
+ virtual BOOL isActive();
+ virtual BOOL callStarted();
+ const std::string& getSessionName() const { return mSessionName; }
+
+ const LLUUID getSessionID() { return mSessionID; }
+ EState getState() { return mState; }
+
+ void updateSessionID(const LLUUID& new_session_id);
+ const LLSD& getNotifyArgs() { return mNotifyArgs; }
+
+ static LLVoiceChannel* getChannelByID(const LLUUID& session_id);
+ static LLVoiceChannel* getChannelByURI(std::string uri);
+ static LLVoiceChannel* getCurrentVoiceChannel() { return sCurrentVoiceChannel; }
+ static void initClass();
+
+ static void suspend();
+ static void resume();
+
+protected:
+ virtual void setState(EState state);
+ void toggleCallWindowIfNeeded(EState state);
+ void setURI(std::string uri);
+
+ std::string mURI;
+ std::string mCredentials;
+ LLUUID mSessionID;
+ EState mState;
+ std::string mSessionName;
+ LLSD mNotifyArgs;
+ BOOL mIgnoreNextSessionLeave;
+ LLHandle<LLPanel> mLoginNotificationHandle;
+
+ typedef std::map<LLUUID, LLVoiceChannel*> voice_channel_map_t;
+ static voice_channel_map_t sVoiceChannelMap;
+
+ typedef std::map<std::string, LLVoiceChannel*> voice_channel_map_uri_t;
+ static voice_channel_map_uri_t sVoiceChannelURIMap;
+
+ static LLVoiceChannel* sCurrentVoiceChannel;
+ static LLVoiceChannel* sSuspendedVoiceChannel;
+ static BOOL sSuspended;
+};
+
+class LLVoiceChannelGroup : public LLVoiceChannel
+{
+public:
+ LLVoiceChannelGroup(const LLUUID& session_id, const std::string& session_name);
+
+ /*virtual*/ void handleStatusChange(EStatusType status);
+ /*virtual*/ void handleError(EStatusType status);
+ /*virtual*/ void activate();
+ /*virtual*/ void deactivate();
+ /*vritual*/ void setChannelInfo(
+ const std::string& uri,
+ const std::string& credentials);
+ /*virtual*/ void getChannelInfo();
+
+protected:
+ virtual void setState(EState state);
+
+private:
+ U32 mRetries;
+ BOOL mIsRetrying;
+};
+
+class LLVoiceChannelProximal : public LLVoiceChannel, public LLSingleton<LLVoiceChannelProximal>
+{
+public:
+ LLVoiceChannelProximal();
+
+ /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
+ /*virtual*/ void handleStatusChange(EStatusType status);
+ /*virtual*/ void handleError(EStatusType status);
+ /*virtual*/ BOOL isActive();
+ /*virtual*/ void activate();
+ /*virtual*/ void deactivate();
+
+};
+
+class LLVoiceChannelP2P : public LLVoiceChannelGroup
+{
+public:
+ LLVoiceChannelP2P(const LLUUID& session_id, const std::string& session_name, const LLUUID& other_user_id);
+
+ /*virtual*/ void handleStatusChange(EStatusType status);
+ /*virtual*/ void handleError(EStatusType status);
+ /*virtual*/ void activate();
+ /*virtual*/ void getChannelInfo();
+
+ void setSessionHandle(const std::string& handle, const std::string &inURI);
+
+protected:
+ virtual void setState(EState state);
+
+private:
+ std::string mSessionHandle;
+ LLUUID mOtherUserID;
+ BOOL mReceivedCall;
+};
+
+#endif // LL_VOICECHANNEL_H
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index 02f63a848b..2834284a9b 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -57,13 +57,13 @@
#include "llagent.h"
#include "llcachename.h"
#include "llimview.h" // for LLIMMgr
-#include "llimpanel.h" // for LLVoiceChannel
#include "llparcel.h"
#include "llviewerparcelmgr.h"
#include "llfirstuse.h"
#include "llviewerwindow.h"
#include "llviewercamera.h"
#include "llvoavatarself.h"
+#include "llvoicechannel.h"
#include "llfloaterfriends.h" //VIVOX, inorder to refresh communicate panel
#include "llfloaterchat.h" // for LLFloaterChat::addChat()
diff --git a/indra/newview/llwearable.cpp b/indra/newview/llwearable.cpp
index 8f74ea29ac..4cd29bb838 100644
--- a/indra/newview/llwearable.cpp
+++ b/indra/newview/llwearable.cpp
@@ -185,7 +185,9 @@ void LLWearable::createVisualParams()
{
delete mVisualParamIndexMap[param->getID()];
}
- mVisualParamIndexMap[param->getID()] = param->cloneParam(this);
+ LLViewerVisualParam *new_param = param->cloneParam(this);
+ new_param->setIsDummy(FALSE);
+ mVisualParamIndexMap[param->getID()] = new_param;
}
}
@@ -545,7 +547,7 @@ BOOL LLWearable::isDirty() const
else
{
// image found in current image list but not saved image list
- return FALSE;
+ return TRUE;
}
}
}
@@ -668,21 +670,7 @@ void LLWearable::writeToAvatar( BOOL set_by_user, BOOL update_customize_floater
if( gFloaterCustomize && update_customize_floater )
{
- LLViewerInventoryItem* item;
- // MULTI_WEARABLE:
- item = (LLViewerInventoryItem*)gInventory.getItem(gAgentWearables.getWearableItemID(mType,0));
- U32 perm_mask = PERM_NONE;
- BOOL is_complete = FALSE;
- if(item)
- {
- perm_mask = item->getPermissions().getMaskOwner();
- is_complete = item->isComplete();
- if(!is_complete)
- {
- item->fetchFromServer();
- }
- }
- gFloaterCustomize->setWearable(mType, this, perm_mask, is_complete);
+ gFloaterCustomize->setWearable(mType, 0);
gFloaterCustomize->setCurrentWearableType( mType );
}
@@ -935,6 +923,17 @@ void LLWearable::getVisualParams(visual_param_vec_t &list)
}
}
+void LLWearable::animateParams(F32 delta, BOOL set_by_user)
+{
+ for(visual_param_index_map_t::iterator iter = mVisualParamIndexMap.begin();
+ iter != mVisualParamIndexMap.end();
+ ++iter)
+ {
+ LLVisualParam *param = (LLVisualParam*) iter->second;
+ param->animate(delta, set_by_user);
+ }
+}
+
LLColor4 LLWearable::getClothesColor(S32 te) const
{
LLColor4 color;
diff --git a/indra/newview/llwearable.h b/indra/newview/llwearable.h
index 01bd9652a5..96631811c5 100644
--- a/indra/newview/llwearable.h
+++ b/indra/newview/llwearable.h
@@ -119,6 +119,7 @@ public:
F32 getVisualParamWeight(S32 index) const;
LLVisualParam* getVisualParam(S32 index) const;
void getVisualParams(visual_param_vec_t &list);
+ void animateParams(F32 delta, BOOL set_by_user);
LLColor4 getClothesColor(S32 te) const;
void setClothesColor( S32 te, const LLColor4& new_color, BOOL set_by_user );
diff --git a/indra/newview/skins/default/textures/map_avatar_8.tga b/indra/newview/skins/default/textures/map_avatar_8.tga
index 47c8cbed6f..28552f2237 100644
--- a/indra/newview/skins/default/textures/map_avatar_8.tga
+++ b/indra/newview/skins/default/textures/map_avatar_8.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 3d1cb84993..401f32c908 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -7,7 +7,7 @@
<texture name="Accordion_Off" file_name="containers/Accordion_Off.png" preload="false" />
<texture name="Accordion_Press" file_name="containers/Accordion_Press.png" preload="false" />
- <texture name="Activate_Checkmark" file_name="taskpanel/Activate_Checkmark.png" preload="false" />
+<texture name="Activate_Checkmark" file_name="taskpanel/Activate_Checkmark.png" preload="false" />
<texture name="AddItem_Disabled" file_name="icons/AddItem_Disabled.png" preload="false" />
<texture name="AddItem_Off" file_name="icons/AddItem_Off.png" preload="false" />
@@ -54,11 +54,6 @@
<texture name="CameraView_Off" file_name="bottomtray/CameraView_Off.png" preload="false" />
<texture name="CameraView_Over" file_name="bottomtray/CameraView_Over.png" preload="false" />
- <texture name="CameraPreset_Rear" file_name="camera_presets/camera_presets_rear.png" preload="false" />
- <texture name="CameraPreset_3_4" file_name="camera_presets/camera_presets_3_4.png" preload="false" />
- <texture name="CameraPreset_Front" file_name="camera_presets/camera_presets_front.png" preload="false" />
- <texture name="CameraPreset_Mouselook" file_name="camera_presets/camera_presets_mouselook.png" preload="false" />
-
<texture name="Checkbox_Off_Disabled" file_name="widgets/Checkbox_Disabled.png" preload="true" />
<texture name="Checkbox_On_Disabled" file_name="widgets/Checkbox_On_Disabled.png" preload="true" />
<texture name="Checkbox_Off" file_name="widgets/Checkbox_Off.png" preload="true" />
@@ -93,7 +88,7 @@
<texture name="Favorite_Star_Press" file_name="navbar/Favorite_Star_Press.png" preload="false" />
<texture name="Favorite_Star_Over" file_name="navbar/Favorite_Star_Over.png" preload="false" />
- <texture name="FileMenu_BarSelect" file_name="navbar/FileMenu_BarSelect.png" preload="false" />
+ <texture name="FileMenu_BarSelect" file_name="navbar/FileMenu_BarSelect.png" preload="false" scale.left="2" scale.top="0" scale.right="2" scale.bottom="0" />
<texture name="FileMenu_BG" file_name="navbar/FileMenu_BG.png" preload="false" />
<texture name="ForwardArrow_Off" file_name="icons/ForwardArrow_Off.png" preload="false" />
@@ -101,7 +96,6 @@
<texture name="Generic_Group" file_name="icons/Generic_Group.png" preload="false" />
<texture name="Generic_Group_Large" file_name="icons/Generic_Group_Large.png" preload="false" />
- <texture name="Generic_Object" file_name="icons/Generic_Object.png" preload="false" />
<texture name="Generic_Person" file_name="icons/Generic_Person.png" preload="false" />
<texture name="Generic_Person_Large" file_name="icons/Generic_Person_Large.png" preload="false" />
@@ -144,6 +138,7 @@
<texture name="Info" file_name="icons/Info.png" preload="false" />
<texture name="Info_Small" file_name="icons/Info_Small.png" preload="false" />
<texture name="Info_Off" file_name="navbar/Info_Off.png" preload="false" />
+ <texture name="Info_Over" file_name="icons/Info_Over.png" preload="false" />
<texture name="Info_Press" file_name="navbar/Info_Press.png" preload="false" />
<texture name="Inspector_Background" file_name="windows/Inspector_Background.png" preload="false"
@@ -151,6 +146,7 @@
<texture name="Inspector_Hover" file_name="windows/Inspector_Hover.png" preload="false" />
<texture name="Inv_Acessories" file_name="icons/Inv_Accessories.png" preload="false" />
+ <texture name="Inv_Alpha" file_name="icons/Inv_Alpha.png" preload="false" />
<texture name="Inv_Animation" file_name="icons/Inv_Animation.png" preload="false" />
<texture name="Inv_BodyShape" file_name="icons/Inv_BodyShape.png" preload="false" />
<texture name="Inv_CallingCard" file_name="icons/Inv_CallingCard.png" preload="false" />
@@ -175,6 +171,7 @@
<texture name="Inv_Snapshot" file_name="icons/Inv_Snapshot.png" preload="false" />
<texture name="Inv_Socks" file_name="icons/Inv_Socks.png" preload="false" />
<texture name="Inv_Sound" file_name="icons/Inv_Sound.png" preload="false" />
+ <texture name="Inv_Tattoo" file_name="icons/Inv_Tattoo.png" preload="false" />
<texture name="Inv_Texture" file_name="icons/Inv_Texture.png" preload="false" />
<texture name="Inv_Trash" file_name="icons/Inv_Trash.png" preload="false" />
<texture name="Inv_Underpants" file_name="icons/Inv_Underpants.png" preload="false" />
@@ -228,9 +225,6 @@
<texture name="NearbyVoice_Lvl3" file_name="bottomtray/NearbyVoice_Lvl3.png" preload="false" />
<texture name="NearbyVoice_On" file_name="bottomtray/NearbyVoice_On.png" preload="false" />
- <texture name="NoEntryLines" file_name="world/NoEntryLines.png" use_mips="true" preload="false" />
- <texture name="NoEntryPassLines" file_name="world/NoEntryPassLines.png" use_mips="true" preload="false" />
-
<texture name="Object_Cone" file_name="build/Object_Cone.png" preload="false" />
<texture name="Object_Cube" file_name="build/Object_Cube.png" preload="false" />
<texture name="Object_Cylinder" file_name="build/Object_Cylinder.png" preload="false" />
@@ -258,42 +252,6 @@
<texture name="Overhead_M" file_name="world/Overhead_M.png" preload="false" />
<texture name="Overhead_S" file_name="world/Overhead_S.png" preload="false" />
- <texture name="parcel_drk_Build" file_name="icons/parcel_drk_Build.png" preload="false" />
- <texture name="parcel_drk_BuildNo" file_name="icons/parcel_drk_BuildNo.png" preload="false" />
- <texture name="parcel_drk_Damage" file_name="icons/parcel_drk_Damage.png" preload="false" />
- <texture name="parcel_drk_DamageNo" file_name="icons/parcel_drk_DamageNo.png" preload="false" />
- <texture name="parcel_drk_Fly" file_name="icons/parcel_drk_Fly.png" preload="false" />
- <texture name="parcel_drk_FlyNo" file_name="icons/parcel_drk_FlyNo.png" preload="false" />
- <texture name="parcel_drk_ForSale" file_name="icons/parcel_drk_ForSale.png" preload="false" />
- <texture name="parcel_drk_ForSaleNo" file_name="icons/parcel_drk_ForSaleNo.png" preload="false" />
- <texture name="parcel_drk_M" file_name="icons/parcel_drk_M.png" preload="false" />
- <texture name="parcel_drk_PG" file_name="icons/parcel_drk_PG.png" preload="false" />
- <texture name="parcel_drk_Push" file_name="icons/parcel_drk_Push.png" preload="false" />
- <texture name="parcel_drk_PushNo" file_name="icons/parcel_drk_PushNo.png" preload="false" />
- <texture name="parcel_drk_R" file_name="icons/parcel_drk_R.png" preload="false" />
- <texture name="parcel_drk_Scripts" file_name="icons/parcel_drk_Scripts.png" preload="false" />
- <texture name="parcel_drk_ScriptsNo" file_name="icons/parcel_drk_ScriptsNo.png" preload="false" />
- <texture name="parcel_drk_Voice" file_name="icons/parcel_drk_Voice.png" preload="false" />
- <texture name="parcel_drk_VoiceNo" file_name="icons/parcel_drk_VoiceNo.png" preload="false" />
-
- <texture name="parcel_lght_Build" file_name="icons/parcel_lght_Build.png" preload="false" />
- <texture name="parcel_lght_BuildNo" file_name="icons/parcel_lght_BuildNo.png" preload="false" />
- <texture name="parcel_lght_Damage" file_name="icons/parcel_lght_Damage.png" preload="false" />
- <texture name="parcel_lght_DamageNo" file_name="icons/parcel_lght_DamageNo.png" preload="false" />
- <texture name="parcel_lght_Fly" file_name="icons/parcel_lght_Fly.png" preload="false" />
- <texture name="parcel_lght_FlyNo" file_name="icons/parcel_lght_FlyNo.png" preload="false" />
- <texture name="parcel_lght_ForSale" file_name="icons/parcel_lght_ForSale.png" preload="false" />
- <texture name="parcel_lght_ForSaleNo" file_name="icons/parcel_lght_ForSaleNo.png" preload="false" />
- <texture name="parcel_lght_M" file_name="icons/parcel_lght_M.png" preload="false" />
- <texture name="parcel_lght_PG" file_name="icons/parcel_lght_PG.png" preload="false" />
- <texture name="parcel_lght_Push" file_name="icons/parcel_lght_Push.png" preload="false" />
- <texture name="parcel_lght_PushNo" file_name="icons/parcel_lght_PushNo.png" preload="false" />
- <texture name="parcel_lght_R" file_name="icons/parcel_lght_R.png" preload="false" />
- <texture name="parcel_lght_Scripts" file_name="icons/parcel_lght_Scripts.png" preload="false" />
- <texture name="parcel_lght_ScriptsNo" file_name="icons/parcel_lght_ScriptsNo.png" preload="false" />
- <texture name="parcel_lght_Voice" file_name="icons/parcel_lght_Voice.png" preload="false" />
- <texture name="parcel_lght_VoiceNo" file_name="icons/parcel_lght_VoiceNo.png" preload="false" />
-
<texture name="Progress_1" file_name="icons/Progress_1.png" preload="false" />
<texture name="Progress_2" file_name="icons/Progress_2.png" preload="false" />
<texture name="Progress_3" file_name="icons/Progress_3.png" preload="false" />
@@ -484,9 +442,6 @@
<!--WARNING OLD ART *do not use*-->
- <texture name="Banner_ForSale" file_name="Banner_ForSale.png" preload="false" />
- <texture name="Banner_YouAreHere" file_name="Banner_YouAreHere.png" preload="false" />
-
<texture name="btn_chatbar.tga" scale.left="20" scale.top="24" scale.right="44" scale.bottom="0" />
<texture name="btn_chatbar_selected.tga" scale.left="20" scale.top="24" scale.right="44" scale.bottom="0" />
@@ -604,6 +559,54 @@
<texture name="icon_popular.tga" />
<texture name="icon_top_pick.tga" />
+ <texture name="inv_folder_animation.tga" />
+ <texture name="inv_folder_bodypart.tga" />
+ <texture name="inv_folder_callingcard.tga" />
+ <texture name="inv_folder_clothing.tga" />
+ <texture name="inv_folder_current_outfit.tga" />
+ <texture name="inv_folder_gesture.tga" />
+ <texture name="inv_folder_landmark.tga" />
+ <texture name="inv_folder_lostandfound.tga" />
+ <texture name="inv_folder_my_outfits.tga" />
+ <texture name="inv_folder_notecard.tga" />
+ <texture name="inv_folder_object.tga" />
+ <texture name="inv_folder_outfit.tga" />
+ <texture name="inv_folder_plain_closed.tga" />
+ <texture name="inv_folder_script.tga" />
+ <texture name="inv_folder_snapshot.tga" />
+ <texture name="inv_folder_sound.tga" />
+ <texture name="inv_folder_texture.tga" />
+ <texture name="inv_folder_trash.tga" />
+
+ <texture name="inv_item_animation.tga" />
+ <texture name="inv_item_skin.tga" />
+ <texture name="inv_item_callingcard_offline.tga" />
+ <texture name="inv_item_callingcard_online.tga" />
+ <texture name="inv_item_eyes.tga" />
+ <texture name="inv_item_gesture.tga" />
+ <texture name="inv_item_gloves.tga" />
+ <texture name="inv_item_hair.tga" />
+ <texture name="inv_item_jacket.tga" />
+ <texture name="inv_item_landmark.tga" />
+ <texture name="inv_item_landmark_visited.tga" />
+ <texture name="inv_item_linkitem.tga" />
+ <texture name="inv_item_linkfolder.tga" />
+ <texture name="inv_item_notecard.tga" />
+ <texture name="inv_item_object.tga" />
+ <texture name="inv_item_object_multi.tga" />
+ <texture name="inv_item_pants.tga" />
+ <texture name="inv_item_script.tga" />
+ <texture name="inv_item_shape.tga" />
+ <texture name="inv_item_shirt.tga" />
+ <texture name="inv_item_shoes.tga" />
+ <texture name="inv_item_skirt.tga" />
+ <texture name="inv_item_snapshot.tga" />
+ <texture name="inv_item_socks.tga" />
+ <texture name="inv_item_sound.tga" />
+ <texture name="inv_item_texture.tga" />
+ <texture name="inv_item_underpants.tga" />
+ <texture name="inv_item_undershirt.tga" />
+
<texture name="lag_status_critical.tga" />
<texture name="lag_status_good.tga" />
<texture name="lag_status_warning.tga" />
@@ -622,12 +625,45 @@
<texture name="media_icon.tga" file_name="icn_label_media.tga" />
<texture name="music_icon.tga" file_name="icn_label_music.tga" />
+ <texture name="NoEntryLines" file_name="world/NoEntryLines.png" use_mips="true" preload="false" />
+ <texture name="NoEntryPassLines" file_name="world/NoEntryPassLines.png" use_mips="true" preload="false" />
<texture name="notify_tip_icon.tga" />
<texture name="notify_caution_icon.tga" />
<texture name="notify_next.png" preload="true" />
<texture name="notify_box_icon.tga" />
+ <texture name="object_cone.tga" />
+ <texture name="object_cone_active.tga" />
+ <texture name="object_cube.tga" />
+ <texture name="object_cube_active.tga" />
+ <texture name="object_cylinder.tga" />
+ <texture name="object_cylinder_active.tga" />
+ <texture name="object_grass.tga" />
+ <texture name="object_grass_active.tga" />
+ <texture name="object_hemi_cone.tga" />
+ <texture name="object_hemi_cone_active.tga" />
+ <texture name="object_hemi_cylinder.tga" />
+ <texture name="object_hemi_cylinder_active.tga" />
+ <texture name="object_hemi_sphere.tga" />
+ <texture name="object_hemi_sphere_active.tga" />
+ <texture name="object_prism.tga" />
+ <texture name="object_prism_active.tga" />
+ <texture name="object_pyramid.tga" />
+ <texture name="object_pyramid_active.tga" />
+ <texture name="object_ring.tga" />
+ <texture name="object_ring_active.tga" />
+ <texture name="object_sphere.tga" />
+ <texture name="object_sphere_active.tga" />
+ <texture name="object_tetrahedron.tga" />
+ <texture name="object_tetrahedron_active.tga" />
+ <texture name="object_torus.tga" />
+ <texture name="object_torus_active.tga" />
+ <texture name="object_tree.tga" />
+ <texture name="object_tree_active.tga" />
+ <texture name="object_tube.tga" />
+ <texture name="object_tube_active.tga" />
+
<texture name="pixiesmall.j2c" use_mips="true" />
<texture name="script_error.j2c" use_mips="true" />
<texture name="silhouette.j2c" use_mips="true" />
@@ -643,6 +679,11 @@
<texture name="status_no_push.tga" />
<texture name="status_no_scripts.tga" />
+ <texture name="tool_dozer.tga" />
+ <texture name="tool_dozer_active.tga" />
+ <texture name="tool_zoom.tga" />
+ <texture name="tool_zoom_active.tga" />
+
<texture name="icn_active-speakers-dot-lvl0.tga" />
<texture name="icn_active-speakers-dot-lvl1.tga" />
<texture name="icn_active-speakers-dot-lvl2.tga" />
diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml
index b194b533af..5cd11ba292 100644
--- a/indra/newview/skins/default/xui/en/floater_about.xml
+++ b/indra/newview/skins/default/xui/en/floater_about.xml
@@ -7,66 +7,56 @@
save_rect="true"
title="About [APP_NAME]"
width="470">
- <floater.string
- name="you_are_at">
- You are at [POSITION]
- </floater.string>
- <floater.string
- name="in_region">
- in [REGION] located at
- </floater.string>
- <floater.string
- name="CPU">
- CPU:
- </floater.string>
- <floater.string
- name="Memory">
- Memory: [MEM] MB
- </floater.string>
- <floater.string
- name="OSVersion">
- OS Version:
- </floater.string>
- <floater.string
- name="GraphicsCardVendor">
- Graphics Card Vendor:
- </floater.string>
- <floater.string
- name="GraphicsCard">
- Graphics Card:
- </floater.string>
- <floater.string
- name="OpenGLVersion">
- OpenGL Version:
- </floater.string>
- <floater.string
- name="LibCurlVersion">
- libcurl Version:
- </floater.string>
- <floater.string
- name="J2CDecoderVersion">
- J2C Decoder Version:
- </floater.string>
- <floater.string
- name="AudioDriverVersion">
- Audio Driver Version:
- </floater.string>
- <floater.string
- name="none">
- (none)
- </floater.string>
- <floater.string
- name="LLMozLibVersion">
- LLMozLib Version:
- </floater.string>
<floater.string
- name="LLQtWebkitVersion">
- Qt Webkit Version: 4.5.2
+ name="AboutHeader">
+[APP_NAME] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2] ([VIEWER_VERSION_3]) [BUILD_DATE] [BUILD_TIME] ([CHANNEL])
+[[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]]
+
+</floater.string>
+ <floater.string
+ name="AboutCompiler">
+Built with [COMPILER] version [COMPILER_VERSION]
+
+</floater.string>
+ <floater.string
+ name="AboutPosition">
+You are at [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] in [REGION] located at [HOSTNAME] ([HOSTIP])
+[SERVER_VERSION]
+[[SERVER_RELEASE_NOTES_URL] [ReleaseNotes]]
+
+</floater.string>
+ <!-- *NOTE: Do not translate text like GPU, Graphics Card, etc -
+ Most PC users who know what these mean will be used to the English versions,
+ and this info sometimes gets sent to support. -->
+ <floater.string
+ name="AboutSystem">
+CPU: [CPU]
+Memory: [MEMORY_MB] MB
+OS Version: [OS_VERSION]
+Graphics Card Vendor: [GRAPHICS_CARD_VENDOR]
+Graphics Card: [GRAPHICS_CARD]
+</floater.string>
+ <floater.string
+ name="AboutDriver">
+Windows Graphics Driver Version: [GRAPHICS_DRIVER_VERSION]
+</floater.string>
+ <floater.string
+ name="AboutLibs">
+OpenGL Version: [OPENGL_VERSION]
+
+libcurl Version: [LIBCURL_VERSION]
+J2C Decoder Version: [J2C_VERSION]
+Audio Driver Version: [AUDIO_DRIVER_VERSION]
+Qt Webkit Version: [QT_WEBKIT_VERSION]
+</floater.string>
+ <floater.string
+ name="none">
+ (none)
</floater.string>
<floater.string
- name="PacketsLost">
- Packets Lost: [LOST]/[IN] ([PCT]%)
- </floater.string>
+ name="AboutTraffic">
+Packets Lost: [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%)
+</floater.string>
<tab_container
follows="all"
top="25"
diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml
index 072fafd06e..aa0b4094b4 100644
--- a/indra/newview/skins/default/xui/en/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_about_land.xml
@@ -28,7 +28,9 @@
follows="left|top|right|bottom"
height="400"
layout="topleft"
+ font="SansSerifSmall"
left="1"
+ tab_padding_right="5"
name="landtab"
tab_position="top"
top="20"
diff --git a/indra/newview/skins/default/xui/en/floater_camera.xml b/indra/newview/skins/default/xui/en/floater_camera.xml
index 520249c2a2..a713cc32a0 100644
--- a/indra/newview/skins/default/xui/en/floater_camera.xml
+++ b/indra/newview/skins/default/xui/en/floater_camera.xml
@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
can_dock="true"
- can_minimize="true"
- can_close="true"
+ can_minimize="false"
+ can_close="true"
center_horiz="true"
- follows="top"
- height="110"
+ follows="bottom"
+ height="152"
layout="topleft"
name="camera_floater"
help_topic="camera_floater"
save_rect="true"
save_visibility="true"
- width="105">
+ width="150">
<floater.string
name="rotate_tooltip">
Rotate Camera Around Focus
@@ -25,69 +25,71 @@
Move Camera Up and Down, Left and Right
</floater.string>
<panel
- border="true"
- height="79"
+ border="false"
+ height="110"
layout="topleft"
- left="0"
+ left="2"
top="0"
- mouse_opaque="false"
+ mouse_opaque="false"
name="controls"
- width="105">
- <joystick_rotate
- follows="top|left"
- height="64"
- image_selected="cam_rotate_in.tga"
- image_unselected="cam_rotate_out.tga"
- layout="topleft"
- left="2"
- name="cam_rotate_stick"
- picture_style="true"
- quadrant="left"
- scale_image="false"
- sound_flags="3"
- tool_tip="Orbit camera around focus"
- top="15"
- width="64" />
+ width="148">
<joystick_track
follows="top|left"
- height="64"
- image_selected="cam_tracking_in.tga"
- image_unselected="cam_tracking_out.tga"
+ height="78"
+ image_selected="Cam_Tracking_In"
+ image_unselected="Cam_Tracking_Out"
layout="topleft"
- left="2"
+ left="45"
name="cam_track_stick"
picture_style="true"
quadrant="left"
scale_image="false"
sound_flags="3"
tool_tip="Move camera up and down, left and right"
- top="15"
+ top="22"
visible="false"
- width="64" />
+ width="78" />
+ <!--TODO: replace with slider, + - images -->
<joystick_zoom
follows="top|left"
- height="64"
- image_unselected="cam_zoom_out.tga"
+ height="78"
+ image_unselected="ScrollThumb_Vert"
layout="topleft"
- left_delta="70"
- minus_image="cam_zoom_minus_in.tga"
+ left="7"
+ minus_image="ScrollThumb_Vert"
name="zoom"
picture_style="true"
- plus_image="cam_zoom_plus_in.tga"
+ plus_image="ScrollThumb_Vert"
quadrant="left"
scale_image="false"
sound_flags="3"
tool_tip="Zoom camera toward focus"
- top_delta="0"
- width="16" />
+ top="22"
+ width="20" />
+ <joystick_rotate
+ follows="top|left"
+ height="78"
+ image_selected="Cam_Rotate_In"
+ image_unselected="Cam_Rotate_Out"
+ layout="topleft"
+ left="45"
+ name="cam_rotate_stick"
+ picture_style="true"
+ quadrant="left"
+ scale_image="false"
+ sound_flags="3"
+ visible="true"
+ tool_tip="Orbit camera around focus"
+ top="22"
+ width="78" />
<panel
- height="70"
+ height="78"
layout="topleft"
- left="15"
+ left="36"
name="camera_presets"
- top="15"
+ top="30"
visible="false"
- width="75">
+ width="78">
<button
height="30"
image_selected="CameraPreset_Rear"
@@ -127,7 +129,7 @@
name="front_view"
picture_style="true"
tool_tip="Front View"
- top_pad="2"
+ top_pad="5"
width="30">
<click_callback
function="CameraPresets.ChangeView"
@@ -151,21 +153,21 @@
</panel>
</panel>
<panel
- border="true"
- height="25"
+ border="false"
+ height="42"
layout="topleft"
- left="0"
- top_pad="1"
+ left="2"
+ top_pad="0"
name="buttons"
- width="105">
+ width="148">
<button
height="23"
label=""
layout="topleft"
- left="2"
+ left="23"
is_toggle="true"
image_overlay="Cam_Orbit_Off"
- image_selected="PushButton_Selected_Press"
+ image_selected="PushButton_Selected_Press"
name="orbit_btn"
tab_stop="false"
tool_tip="Orbit camera"
@@ -179,7 +181,7 @@
left_pad="0"
is_toggle="true"
image_overlay="Cam_Pan_Off"
- image_selected="PushButton_Selected_Press"
+ image_selected="PushButton_Selected_Press"
name="pan_btn"
tab_stop="false"
tool_tip="Pan camera"
@@ -191,7 +193,7 @@
layout="topleft"
left_pad="0"
image_overlay="Cam_Avatar_Off"
- image_selected="PushButton_Selected_Press"
+ image_selected="PushButton_Selected_Press"
name="avatarview_btn"
tab_stop="false"
tool_tip="See as avatar"
@@ -204,12 +206,11 @@
left_pad="0"
is_toggle="true"
image_overlay="Cam_FreeCam_Off"
- image_selected="PushButton_Selected_Press"
+ image_selected="PushButton_Selected_Press"
name="freecamera_btn"
tab_stop="false"
tool_tip="View object"
width="25">
</button>
-
</panel>
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
index 0bd4b441c6..d24d1b7064 100644
--- a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
+++ b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
@@ -14,7 +14,7 @@
save_rect="true"
title="Nearby Chat"
save_visibility="true"
- single_instance="true"
+ single_instance="true"
width="320">
<chat_history
allow_html="true"
diff --git a/indra/newview/skins/default/xui/en/floater_pay.xml b/indra/newview/skins/default/xui/en/floater_pay.xml
index 5f70f09a34..69525d48d2 100644
--- a/indra/newview/skins/default/xui/en/floater_pay.xml
+++ b/indra/newview/skins/default/xui/en/floater_pay.xml
@@ -34,7 +34,7 @@
type="string"
length="1"
follows="left|top"
- font="SansSerif"
+ font="SansSerifSmall"
height="16"
layout="topleft"
left_pad="7"
@@ -44,6 +44,7 @@
</text>
<button
height="23"
+ font="SansSerifSmall"
label="L$1"
label_selected="L$1"
layout="topleft"
@@ -53,7 +54,8 @@
width="80" />
<button
height="23"
- label="L$5"
+ label="L$1"
+ font="SansSerif"
label_selected="L$5"
layout="topleft"
left_pad="15"
@@ -62,6 +64,7 @@
<button
height="23"
label="L$10"
+ font="SansSerifHuge"
label_selected="L$10"
layout="topleft"
left="25"
diff --git a/indra/newview/skins/default/xui/en/floater_preferences.xml b/indra/newview/skins/default/xui/en/floater_preferences.xml
index 285045f2c8..90a77b22b6 100644
--- a/indra/newview/skins/default/xui/en/floater_preferences.xml
+++ b/indra/newview/skins/default/xui/en/floater_preferences.xml
@@ -12,32 +12,32 @@
width="620">
<button
follows="right|bottom"
- height="20"
+ height="23"
label="OK"
label_selected="OK"
layout="topleft"
- left="427"
+ right="-105"
name="OK"
- top="435"
+ top="433"
width="90">
<button.commit_callback
function="Pref.OK" />
</button>
<button
follows="right|bottom"
- height="20"
+ height="23"
label="Cancel"
label_selected="Cancel"
layout="topleft"
- left_pad="3"
+ left_pad="5"
name="Cancel"
- top_delta="0"
+ right="-10"
width="90" >
<button.commit_callback
function="Pref.Cancel" />
</button>
<tab_container
- follows="left|top|right|bottom"
+ follows="all"
height="410"
layout="topleft"
left="0"
@@ -48,14 +48,14 @@
top="21"
width="620">
<panel
- class="panel_preference"
+ class="panel_preference"
filename="panel_preferences_general.xml"
label="General"
layout="topleft"
help_topic="preferences_general_tab"
name="general" />
<panel
- class="panel_preference"
+ class="panel_preference"
filename="panel_preferences_graphics1.xml"
label="Graphics"
layout="topleft"
@@ -103,13 +103,6 @@
layout="topleft"
help_topic="preferences_advanced1_tab"
name="advanced1" />
- <panel
- class="panel_preference"
- filename="panel_preferences_advanced2.xml"
- label="Move or Kill"
- layout="topleft"
- help_topic="preferences_advanced2_tab"
- name="advanced2" />
</tab_container>
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_preview_notecard.xml b/indra/newview/skins/default/xui/en/floater_preview_notecard.xml
index 8cdafe110a..d2b8455eab 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_notecard.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_notecard.xml
@@ -83,7 +83,7 @@
Loading...
</text_editor>
<button
- follows="left|bottom"
+ follows="right|bottom"
height="22"
label="Save"
label_selected="Save"
diff --git a/indra/newview/skins/default/xui/en/floater_report_abuse.xml b/indra/newview/skins/default/xui/en/floater_report_abuse.xml
index abde4ba5fa..884532c7a3 100644
--- a/indra/newview/skins/default/xui/en/floater_report_abuse.xml
+++ b/indra/newview/skins/default/xui/en/floater_report_abuse.xml
@@ -14,19 +14,19 @@
allow_no_texture="true"
default_image_name="None"
follows="left|top"
- height="125"
+ height="150"
layout="topleft"
- left="10"
- name="screenshot"
- top="23"
- width="160" />
+ left="60"
+ name=""
+ top="15"
+ width="220" />
<check_box
height="15"
label="Use this screenshot"
layout="topleft"
- left_pad="5"
+ left="8"
name="screen_check"
- top="120"
+ top_pad="-12"
width="116" />
<text
type="string"
@@ -38,8 +38,8 @@
layout="topleft"
left="10"
name="reporter_title"
- top="140"
- width="60">
+ top_pad="0"
+ width="100">
Reporter:
</text>
<text
@@ -48,24 +48,25 @@
follows="left|top"
height="16"
layout="topleft"
- left_pad="10"
+ left_pad="5"
name="reporter_field"
top_delta="0"
- width="193">
- Loremipsum Dolorsitamut
+ use_ellipses="true"
+ width="200">
+ Loremipsum Dolorsitamut Longnamez
</text>
<text
type="string"
length="1"
follows="left|top"
height="16"
- font.name="SansSerif"
+ font.name="SansSerif"
font.style="BOLD"
layout="topleft"
left="10"
name="sim_title"
- top_pad="5"
- width="60">
+ top_pad="2"
+ width="100">
Region:
</text>
<text
@@ -74,10 +75,11 @@
follows="left|top"
height="16"
layout="topleft"
- left_pad="2"
+ left_pad="5"
name="sim_field"
top_delta="0"
- width="193">
+ use_ellipses="true"
+ width="200">
Region Name
</text>
<text
@@ -85,13 +87,13 @@
length="1"
follows="left|top"
height="16"
- font.name="SansSerif"
+ font.name="SansSerif"
font.style="BOLD"
layout="topleft"
left="10"
name="pos_title"
- top_pad="5"
- width="50">
+ top_pad="2"
+ width="100">
Position:
</text>
<text
@@ -100,10 +102,10 @@
follows="left|top"
height="16"
layout="topleft"
- left_pad="12"
+ left_pad="5"
name="pos_field"
top_delta="0"
- width="193">
+ width="200">
{128.1, 128.1, 15.4}
</text>
<text
@@ -114,7 +116,7 @@
layout="topleft"
left="10"
name="select_object_label"
- top_pad="5"
+ top_pad="2"
width="310">
Click the button, then the abusive object:
</text>
@@ -133,13 +135,13 @@
length="1"
follows="left|top"
height="16"
- font.name="SansSerif"
+ font.name="SansSerif"
font.style="BOLD"
layout="topleft"
left="48"
name="object_name_label"
top_delta="0"
- width="60">
+ width="80">
Object:
</text>
<text
@@ -151,7 +153,8 @@
left_pad="6"
name="object_name"
top_delta="0"
- width="157">
+ use_ellipses="true"
+ width="185">
Consetetur Sadipscing
</text>
<text
@@ -159,13 +162,13 @@
length="1"
follows="left|top"
height="16"
- font.name="SansSerif"
+ font.name="SansSerif"
font.style="BOLD"
layout="topleft"
left="48"
name="owner_name_label"
top_pad="0"
- width="60">
+ width="80">
Owner:
</text>
<text
@@ -177,8 +180,9 @@
left_pad="6"
name="owner_name"
top_delta="0"
- width="157">
- Hendrerit Vulputate
+ use_ellipses="true"
+ width="185">
+ Hendrerit Vulputate Kamawashi Longname
</text>
<combo_box
height="23"
@@ -349,8 +353,8 @@
type="string"
length="1"
follows="left|top"
- height="16"
- font.name="SansSerif"
+ height="14"
+ font.name="SansSerif"
font.style="BOLD"
layout="topleft"
left_delta="0"
@@ -368,11 +372,10 @@
left_delta="0"
max_length="32"
name="abuser_name_edit"
- top_pad="2"
+ top_pad="0"
width="195" />
<button
height="23"
- font="SansSerifSmall"
label="Choose"
layout="topleft"
left_pad="5"
@@ -394,13 +397,13 @@
type="string"
length="1"
follows="left|top"
- height="16"
- font.name="SansSerif"
+ height="14"
+ font.name="SansSerif"
font.style="BOLD"
layout="topleft"
left="10"
name="abuser_name_title2"
- top_pad="5"
+ top_pad="2"
width="313">
Location of Abuse:
</text>
@@ -413,19 +416,19 @@
left="10"
max_length="256"
name="abuse_location_edit"
- top_pad="2"
+ top_pad="0"
width="313" />
<text
type="string"
length="1"
follows="left|top"
height="16"
- font.name="SansSerif"
+ font.name="SansSerif"
font.style="BOLD"
layout="topleft"
left_delta="0"
name="sum_title"
- top_pad="5"
+ top_pad="2"
width="313">
Summary:
</text>
@@ -438,14 +441,14 @@
left_delta="0"
max_length="64"
name="summary_edit"
- top_pad="2"
+ top_pad="0"
width="313" />
<text
type="string"
length="1"
follows="left|top"
- height="16"
- font.name="SansSerif"
+ height="14"
+ font.name="SansSerif"
font.style="BOLD"
layout="topleft"
left_delta="0"
@@ -461,9 +464,9 @@
height="16"
layout="topleft"
name="bug_aviso"
- left_pad="0"
+ left_pad="10"
width="200">
- Please be as specific as possible.
+ Please be as specific as possible
</text>
<text_editor
follows="left|top"
@@ -479,16 +482,15 @@
type="string"
length="1"
follows="left|top"
- height="50"
+ height="30"
layout="topleft"
left="10"
- font.name="SansSerif"
- font.style="BOLD"
+ font.name="SansSerifSmall"
name="incomplete_title"
- top_pad="5"
+ top_pad="2"
word_wrap="true"
width="313">
- Note: Incomplete reports won't be investigated.
+ * Incomplete reports won't be investigated
</text>
<button
left="80"
diff --git a/indra/newview/skins/default/xui/en/floater_test_textbox.xml b/indra/newview/skins/default/xui/en/floater_test_textbox.xml
index 8305452c85..c33ab8aa70 100644
--- a/indra/newview/skins/default/xui/en/floater_test_textbox.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_textbox.xml
@@ -114,16 +114,59 @@
Escaped greater than &gt;
</text>
<text
- type="string"
- length="1"
- bottom="390"
- label="N"
- layout="topleft"
- left="10"
- name="floater_map_north"
- right="30"
- text_color="1 1 1 0.7"
- top="370">
- N
- </text>
+ type="string"
+ length="1"
+ bottom="390"
+ label="N"
+ layout="topleft"
+ left="10"
+ name="right_aligned_text"
+ width="380"
+ halign="right"
+ text_color="1 1 1 0.7"
+ top_pad="10">
+ Right aligned text
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom="390"
+ label="N"
+ layout="topleft"
+ left="10"
+ name="centered_text"
+ width="380"
+ halign="center"
+ text_color="1 1 1 0.7"
+ top_pad="10">
+ Centered text
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom="390"
+ label="N"
+ layout="topleft"
+ left="10"
+ name="centered_text"
+ width="380"
+ halign="left"
+ text_color="1 1 1 0.7"
+ top_pad="10">
+ Left aligned text
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom="390"
+ label="N"
+ layout="topleft"
+ left="10"
+ name="floater_map_north"
+ right="30"
+ text_color="1 1 1 0.7"
+ top="370">
+ N
+ </text>
+
</floater>
diff --git a/indra/newview/skins/default/xui/en/menu_object_icon.xml b/indra/newview/skins/default/xui/en/menu_object_icon.xml
new file mode 100644
index 0000000000..0c8a2af002
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_object_icon.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu
+ height="101"
+ layout="topleft"
+ left="100"
+ mouse_opaque="false"
+ name="Object Icon Menu"
+ top="724"
+ visible="false"
+ width="128">
+ <menu_item_call
+ label="Object Profile..."
+ layout="topleft"
+ name="Object Profile">
+ <menu_item_call.on_click
+ function="ObjectIcon.Action"
+ parameter="profile" />
+ </menu_item_call>
+ <menu_item_call
+ label="Block..."
+ layout="topleft"
+ name="Block">
+ <menu_item_call.on_click
+ function="ObjectIcon.Action"
+ parameter="block" />
+ </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml
index cc17e9dd4b..eedb4383bb 100644
--- a/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml
+++ b/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml
@@ -23,9 +23,14 @@
parameter="sort_status" />
</menu_item_check>
<menu_item_separator layout="topleft" />
- <menu_item_call name="view_icons" label="View People Icons">
- <menu_item_call.on_click function="People.Friends.ViewSort.Action" userdata="view_icons" />
- </menu_item_call>
+ <menu_item_check name="view_icons" label="View People Icons">
+ <menu_item_check.on_click
+ function="People.Friends.ViewSort.Action"
+ parameter="view_icons" />
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="FriendsListShowIcons" />
+ </menu_item_check>
<menu_item_call name="organize_offline" label="Organize Offline Friends">
<menu_item_call.on_click function="People.Friends.ViewSort.Action" userdata="organize_offline" />
</menu_item_call>
diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml
index f91a961388..c002cd078f 100644
--- a/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml
+++ b/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml
@@ -12,9 +12,14 @@
<menu_item_call.on_click function="People.Nearby.ViewSort.Action" userdata="sort_distance" />
</menu_item_call>
<menu_item_separator layout="topleft" />
- <menu_item_call name="view_icons" label="View People Icons">
- <menu_item_call.on_click function="People.Nearby.ViewSort.Action" userdata="view_icons" />
- </menu_item_call>
+ <menu_item_check name="view_icons" label="View People Icons">
+ <menu_item_check.on_click
+ function="People.Nearby.ViewSort.Action"
+ parameter="view_icons" />
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="NearbyListShowIcons" />
+ </menu_item_check>
<menu_item_separator layout="topleft" />
<menu_item_call name="show_blocked_list" label="Show Blocked Residents &amp; Objects">
<menu_item_call.on_click function="SideTray.ShowPanel" userdata="panel_block_list_sidetray" />
diff --git a/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml
index d09871cff3..cfd6dc78b6 100644
--- a/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml
+++ b/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml
@@ -23,9 +23,14 @@
parameter="sort_name" />
</menu_item_check>
<menu_item_separator layout="topleft" />
- <menu_item_call name="view_icons" label="View People Icons">
- <menu_item_call.on_click function="People.Recent.ViewSort.Action" userdata="view_icons" />
- </menu_item_call>
+ <menu_item_check name="view_icons" label="View People Icons">
+ <menu_item_check.on_click
+ function="People.Recent.ViewSort.Action"
+ parameter="view_icons" />
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="RecentListShowIcons" />
+ </menu_item_check>
<menu_item_separator layout="topleft" />
<menu_item_call name="show_blocked_list" label="Show Blocked Residents &amp; Objects">
<menu_item_call.on_click function="SideTray.ShowPanel" userdata="panel_block_list_sidetray" />
diff --git a/indra/newview/skins/default/xui/en/menu_place_add_button.xml b/indra/newview/skins/default/xui/en/menu_place_add_button.xml
new file mode 100644
index 0000000000..e3a39a1242
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_place_add_button.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="menu_folder_gear"
+ visible="false">
+ <menu_item_call
+ label="Add Folder"
+ layout="topleft"
+ name="add_folder">
+ <on_click
+ function="Places.LandmarksGear.Add.Action"
+ parameter="category" />
+ <on_enable
+ function="Places.LandmarksGear.Enable"
+ parameter="category" />
+ </menu_item_call>
+ <menu_item_call
+ label="Add Landmark"
+ layout="topleft"
+ name="add_landmark">
+ <on_click
+ function="Places.LandmarksGear.Add.Action"
+ parameter="add_landmark" />
+ </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 7d2ef4923e..9aacb8a92c 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -5837,15 +5837,11 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you a
<button
index="0"
name="Keep"
- text="OK"/>
+ text="Accept"/>
<button
index="1"
name="Discard"
- text="Cancel"/>
- <button
- index="2"
- name="Mute"
- text="Block"/>
+ text="No, thanks"/>
</form>
</notification>
@@ -6151,8 +6147,7 @@ Your L$ balance is shown in the upper-right.
type="notify">
Thank you for your payment!
-When the processing completes, your L$ balance will be updated at the top of your screen.
-If processing your payment takes more than 20 minutes to complete, the purchase amount will be credited to your account for use on your next purchase.
+Your L$ balance will be updated when processing completes. If processing takes more than 20 mins, your transaction may be cancelled. In that case, the purchase amount will be credited to your US$ balance.
The status of your payment can be checked on your Transaction History page at Me > My Dashboard, or http://secondlife.com/account/
</notification>
diff --git a/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml b/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml
new file mode 100644
index 0000000000..8db745fab7
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ name="panel_im_control_panel"
+ width="146"
+ height="215"
+ border="false">
+ <avatar_list
+ color="DkGray2"
+ follows="left|top|right|bottom"
+ height="130"
+ ignore_online_status="true"
+ layout="topleft"
+ left="3"
+ name="speakers_list"
+ opaque="false"
+ top="10"
+ width="140" />
+ <button
+ name="call_btn"
+ label="Call"
+ width="90"
+ height="20" />
+ <button
+ name="end_call_btn"
+ label="End Call"
+ width="90"
+ height="20"
+ visible="false"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml
index f747c557e2..8aaa462aaf 100644
--- a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml
@@ -47,17 +47,17 @@
top="6"
use_ellipses="true"
value="Unknown"
- width="166" />
+ width="196" />
<text
- follows="left"
+ follows="right"
font="SansSerifSmall"
height="15"
layout="topleft"
left_pad="10"
- name="avatar_status"
+ name="last_interaction"
text_color="LtGray_50"
- value="Away"
- width="50" />
+ value="0s"
+ width="24" />
<output_monitor
auto_update="true"
follows="right"
@@ -75,6 +75,7 @@
image_pressed="Info_Press"
image_hover="Info_Over"
image_unselected="Info_Off"
+ layout="topleft"
left_pad="3"
right="-25"
name="info_btn"
diff --git a/indra/newview/skins/default/xui/en/panel_group_control_panel.xml b/indra/newview/skins/default/xui/en/panel_group_control_panel.xml
index 9767a673f6..15b6b2a00d 100644
--- a/indra/newview/skins/default/xui/en/panel_group_control_panel.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_control_panel.xml
@@ -7,12 +7,14 @@
<avatar_list
color="DkGray2"
follows="left|top|right|bottom"
- height="150"
+ height="130"
+ ignore_online_status="true"
layout="topleft"
left="3"
name="speakers_list"
+ opaque="false"
top="10"
- width="140"/>
+ width="140" />
<button
name="group_info_btn"
label="Group Info"
@@ -24,4 +26,10 @@
label="Call"
width="90"
height="20" />
+ <button
+ name="end_call_btn"
+ label="End Call"
+ width="90"
+ height="20"
+ visible="false"/>
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_group_roles.xml b/indra/newview/skins/default/xui/en/panel_group_roles.xml
index 75ded4f249..af1919bd8f 100644
--- a/indra/newview/skins/default/xui/en/panel_group_roles.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_roles.xml
@@ -486,7 +486,7 @@ things in this group. There&apos;s a broad variety of Abilities.
</panel>
</tab_container>
<panel
- height="170"
+ height="190"
layout="topleft"
follows="left|top"
left="10"
@@ -556,7 +556,7 @@ things in this group. There&apos;s a broad variety of Abilities.
</scroll_list>
</panel>
<panel
- height="215"
+ height="252"
layout="topleft"
left_delta="0"
name="roles_footer"
diff --git a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml
index 7dc94d1141..dca52def49 100644
--- a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml
+++ b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel name="panel_im_control_panel"
width="96"
- height="215"
+ height="225"
border="false">
<avatar_icon name="avatar_icon"
@@ -24,6 +24,13 @@
width="90"
height="20" />
+ <button
+ height="20"
+ label="End Call"
+ name="end_call_btn"
+ visible="false"
+ width="90" />
+
<button name="share_btn"
label="Share"
width="90"
diff --git a/indra/newview/skins/default/xui/en/panel_instant_message.xml b/indra/newview/skins/default/xui/en/panel_instant_message.xml
index 00ede1fb2c..26d8304551 100644
--- a/indra/newview/skins/default/xui/en/panel_instant_message.xml
+++ b/indra/newview/skins/default/xui/en/panel_instant_message.xml
@@ -1,15 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
background_visible="true"
- bevel_style="in"
bg_alpha_color="0.3 0.3 0.3 0"
- height="140"
+ height="175"
label="im_panel"
layout="topleft"
left="0"
name="im_panel"
top="0"
- width="350">
+ width="305">
<string
name="message_max_lines_count">
6
@@ -19,50 +18,52 @@
bevel_style="in"
bg_alpha_color="black"
follows="top"
- height="30"
+ height="20"
label="im_header"
layout="topleft"
left="5"
name="im_header"
top="5"
- width="340">
+ width="295">
<avatar_icon
follows="right"
height="20"
image_name="icon_avatar_online.tga"
layout="topleft"
- left="5"
+ left="0"
mouse_opaque="true"
name="avatar_icon"
- top="5"
+ top="0"
width="20" />
<icon
follows="right"
height="20"
image_name="icon_top_pick.tga"
layout="topleft"
- left="5"
+ left="0"
mouse_opaque="true"
name="sys_msg_icon"
- top="5"
+ top="0"
width="20" />
<text
follows="left|right"
- font="SansSerifBigBold"
+ font="SansSerifBold"
height="20"
layout="topleft"
- left_pad="10"
+ left_pad="5"
name="user_name"
text_color="white"
top="5"
value="Darth Vader"
- width="250" />
+ width="295" />
+ <!-- TIME STAMP -->
<text
follows="right"
- font="SansSerifBig"
+ font="SansSerif"
height="20"
layout="topleft"
- left_pad="10"
+ halign="right"
+ left="245"
name="time_box"
text_color="white"
top="5"
@@ -71,25 +72,25 @@
</panel>
<text
follows="left|top|bottom|right"
- height="60"
+ height="86"
layout="topleft"
left="10"
name="message"
text_color="white"
- top="40"
+ top="33"
use_ellipses="true"
value="MESSAGE"
- width="330"
+ width="285"
word_wrap="true"
max_length="350" />
<button
follows="bottom"
- font="SansSerifBigBold"
+ font="SansSerifBold"
height="25"
- label="reply"
+ label="Reply"
layout="topleft"
- left="120"
+ left="97"
name="reply"
- top="110"
+ top="137"
width="110" />
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_landmarks.xml b/indra/newview/skins/default/xui/en/panel_landmarks.xml
index c33f68eaf7..5293043ba7 100644
--- a/indra/newview/skins/default/xui/en/panel_landmarks.xml
+++ b/indra/newview/skins/default/xui/en/panel_landmarks.xml
@@ -114,22 +114,10 @@
image_disabled="AddItem_Disabled"
layout="topleft"
left_pad="5"
- name="add_landmark_btn"
+ name="add_btn"
picture_style="true"
tool_tip="Add new landmark"
width="18" />
- <button
- follows="bottom|left"
- height="18"
- image_selected="AddItem_Press"
- image_unselected="AddItem_Off"
- image_disabled="AddItem_Disabled"
- layout="topleft"
- left_pad="5"
- name="add_folder_btn"
- picture_style="true"
- tool_tip="Add new folder"
- width="18" />
<dnd_button
follows="bottom|right"
height="18"
diff --git a/indra/newview/skins/default/xui/en/panel_notification.xml b/indra/newview/skins/default/xui/en/panel_notification.xml
index 9c2829d92d..0d34aa0f08 100644
--- a/indra/newview/skins/default/xui/en/panel_notification.xml
+++ b/indra/newview/skins/default/xui/en/panel_notification.xml
@@ -1,37 +1,51 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
- background_opaque="true"
- background_visible="false"
+ background_opaque="false"
+ border_visible="false"
+ border = "false"
+ border_drop_shadow_visible = "false"
+ drop_shadow_visible = "false"
+ background_visible="true"
bg_alpha_color="0.3 0.3 0.3 0"
- height="140"
+ bg_opaque_color="0.3 0.3 0.3 0"
label="notification_panel"
layout="topleft"
left="0"
name="notification_panel"
top="0"
- width="350">
+ height="10"
+ width="305">
+ <!-- THIS PANEL CONTROLS TOAST HEIGHT? -->
<panel
+ border_visible="false"
+ drop_shadow="false"
+ bevel_style="none"
+ border_style="none"
+ border = "false"
+ border_drop_shadow_visible = "false"
+ drop_shadow_visible = "false"
background_visible="true"
- bg_alpha_color="0.3 0.3 0.3 0"
+ 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="100"
+ height="10"
label="info_panel"
layout="topleft"
left="0"
name="info_panel"
top="0"
- width="350">
- <text
+ width="305">
+ <!-- <text
border_visible="false"
follows="left|right|top|bottom"
font="SansSerif"
height="90"
layout="topleft"
- left="45"
+ left="10"
name="text_box"
read_only="true"
text_color="white"
- top="5"
+ top="10"
visible="false"
width="300"
wrap="true"/>
@@ -47,40 +61,43 @@
top="5"
visible="false"
width="300"
- wrap="true"/>
+ wrap="true"/> -->
<text_editor
+ h_pad="0"
+ v_pad="0"
bg_readonly_color="0.0 0.0 0.0 0"
border_visible="false"
+ border = "false"
+ border_drop_shadow_visible = "false"
+ drop_shadow_visible = "false"
embedded_items="false"
enabled="false"
follows="left|right|top|bottom"
font="SansSerif"
- height="90"
layout="topleft"
- left="45"
+ left="10"
mouse_opaque="false"
name="text_editor_box"
read_only="true"
tab_stop="false"
text_color="white"
text_readonly_color="white"
- top="5"
+ top="10"
visible="false"
- width="300"
+ width="285"
wrap="true"/>
</panel>
<panel
- background_visible="true"
- bg_alpha_color="0.3 0.3 0.3 0"
+ background_visible="false"
follows="left|right|bottom"
- height="40"
label="control_panel"
layout="topleft"
left="0"
+ left_delta="-38"
name="control_panel"
- top_pad="0"
- width="350">
+ top="20">
</panel>
+ <!--
<icon
follows="left|top"
height="32"
@@ -90,5 +107,5 @@
mouse_opaque="false"
name="info_icon"
top="20"
- width="32" />
+ width="32" /> -->
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml
index 7b19ab1a1c..0db5a41cc5 100644
--- a/indra/newview/skins/default/xui/en/panel_people.xml
+++ b/indra/newview/skins/default/xui/en/panel_people.xml
@@ -49,11 +49,13 @@ background_visible="true"
height="500"
layout="topleft"
left="10"
+ font="SansSerifBigBold"
name="tabs"
tab_min_width="70"
tab_height="30"
tab_position="top"
top_pad="10"
+ halign="center"
width="313">
<panel
follows="all"
@@ -301,6 +303,7 @@ background_visible="true"
left="0"
multi_select="true"
name="avatar_list"
+ show_last_interaction_time="true"
top="2"
width="313" />
<panel
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
index f42bab14de..91dcdce23b 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
@@ -20,8 +20,9 @@
</panel.string>
<check_box
control_name="UseChatBubbles"
+ follows="left|top"
height="16"
- label="Bubble Chat"
+ label="Bubble chat"
layout="topleft"
left="30"
top="10"
@@ -30,6 +31,7 @@
<slider
control_name="ChatBubbleOpacity"
+ follows="left|top"
height="16"
increment="0.05"
initial_value="1"
@@ -40,40 +42,24 @@
label_width="50"
name="bubble_chat_opacity"
width="200" />
-
- <!-- <check_box
- control_name="UIAutoScale"
- height="16"
- label="Resolution independent scale"
- layout="topleft"
- left="30"
- name="ui_auto_scale"
- top_pad="10"
- width="256" />-->
- <!--
- <combo_box
- height="18"
- layout="topleft"
- left_pad="5"
- name="fullscreen combo"
- top_delta="-1"
- width="150" /-->
<text
+ follows="left|top"
type="string"
length="1"
height="25"
layout="topleft"
left="30"
- top_pad="20"
+ top_pad="5"
name="AspectRatioLabel1"
tool_tip="width / height"
label_width="50"
width="120">
- Aspect Ratio
+ Aspect ratio
</text>
<combo_box
allow_text_entry="true"
height="20"
+ follows="left|top"
layout="topleft"
left_pad="0"
max_chars="100"
@@ -104,6 +90,7 @@
</combo_box>
<check_box
control_name="FullScreenAutoDetectAspectRatio"
+ follows="left|top"
height="25"
label="Auto-detect"
layout="topleft"
@@ -113,14 +100,14 @@
<check_box.commit_callback
function="Pref.AutoDetectAspect" />
</check_box>
-
<text
+ follows="left|top"
type="string"
length="1"
height="10"
left="30"
name="heading1"
- top_pad="10"
+ top_pad="5"
width="270">
Camera:
</text>
@@ -128,7 +115,7 @@ Camera:
can_edit_text="true"
control_name="CameraAngle"
decimal_digits="2"
- top_pad="10"
+ top_pad="5"
follows="left|top"
height="16"
increment="0.025"
@@ -159,56 +146,62 @@ Camera:
name="camera_offset_scale"
show_text="false"
width="240"
- top_pad="10"/>
+ top_pad="5"/>
<text
+ follows="left|top"
type="string"
length="1"
height="10"
left="30"
name="heading2"
- width="270">
+ width="270"
+ top_pad="5">
Automatic positioning for:
</text>
<check_box
control_name="EditCameraMovement"
height="20"
+ follows="left|top"
label="Build/Edit"
layout="topleft"
left_delta="50"
name="edit_camera_movement"
tool_tip="Use automatic camera positioning when entering and exiting edit mode"
width="280"
- top_pad="10" />
+ top_pad="5" />
<check_box
control_name="AppearanceCameraMovement"
+ follows="left|top"
height="16"
label="Appearance"
layout="topleft"
name="appearance_camera_movement"
tool_tip="Use automatic camera positioning while in edit mode"
width="242" />
-
<text
+ follows="left|top"
type="string"
length="1"
height="10"
left="30"
name="heading3"
- top_pad="10"
+ top_pad="5"
width="270">
Avatars:
</text>
<check_box
control_name="FirstPersonAvatarVisible"
+ follows="left|top"
height="20"
label="Show me in Mouselook"
layout="topleft"
left_delta="50"
name="first_person_avatar_visible"
width="256"
- top_pad="10"/>
+ top_pad="0"/>
<check_box
control_name="ArrowKeysMoveAvatar"
+ follows="left|top"
height="20"
label="Arrow keys always move me"
layout="topleft"
@@ -218,6 +211,7 @@ Avatars:
top_pad="0"/>
<check_box
control_name="AllowTapTapHoldRun"
+ follows="left|top"
height="20"
label="Tap-tap-hold to run"
layout="topleft"
@@ -227,6 +221,7 @@ Avatars:
top_pad="0"/>
<check_box
control_name="LipSyncEnabled"
+ follows="left|top"
height="20"
label="Move avatar lips when speaking"
layout="topleft"
@@ -236,16 +231,18 @@ Avatars:
top_pad="0" />
<check_box
control_name="ShowScriptErrors"
+ follows="left|top"
height="20"
label="Show script errors"
layout="topleft"
left="30"
name="show_script_errors"
width="256"
- top_pad="10"/>
+ top_pad="5"/>
<radio_group
enabled_control="ShowScriptErrors"
control_name="ShowScriptErrorsLocation"
+ follows="top|left"
draw_border="false"
height="40"
layout="topleft"
@@ -259,17 +256,53 @@ Avatars:
layout="topleft"
left="3"
name="0"
- top="3"
+ top="0"
width="315" />
<radio_item
height="16"
label="In window"
layout="topleft"
- left_delta="0"
+ left_delta="175"
name="1"
- top_delta="16"
+ top_delta="0"
width="315" />
</radio_group>
-
-
+ <check_box
+ follows="top|left"
+ height="20"
+ label="Use Push-to-talk in toggle mode"
+ layout="topleft"
+ left="30"
+ name="push_to_talk_toggle_check"
+ width="237"
+ top_pad="-25"
+ tool_tip="When in toggle mode, press and release the push-to-talk trigger to switch your microphone on and off. When not in toggle mode, the microphone is active only when the trigger is held down."/>
+ <line_editor
+ follows="top|left"
+ height="19"
+ left_delta="50"
+ max_length="254"
+ name="modifier_combo"
+ label="Push-to-talk trigger"
+ top_pad="0"
+ width="280" />
+ <button
+ follows="top|left"
+ height="20"
+ label="Set Key"
+ left_delta="0"
+ name="set_voice_hotkey_button"
+ width="115"
+ top_pad="5" />
+ <button
+ bottom_delta="0"
+ follows="left"
+ font="SansSerif"
+ halign="center"
+ height="20"
+ label="Middle Mouse Button"
+ left_delta="120"
+ mouse_opaque="true"
+ name="set_voice_middlemouse_button"
+ width="160" />
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
index b1093ba17b..832c9775ce 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
border="true"
- follows="left|top|right|bottom"
+ follows="all"
height="408"
- label="Audio &amp; Video"
+ label="Sounds"
layout="topleft"
left="102"
name="Preference Media panel"
@@ -12,18 +12,20 @@
<slider
control_name="AudioLevelMaster"
follows="left|top"
+ font.style="BOLD"
height="15"
increment="0.05"
initial_value="0.5"
label="Master volume"
- label_width="125"
+ label_width="160"
layout="topleft"
- left="30"
+ left="0"
name="System Volume"
show_text="false"
+ slider_label.halign="right"
top_pad="5"
volume="true"
- width="425">
+ width="350">
<slider.commit_callback
function="Pref.setControlFalse"
parameter="MuteAudio" />
@@ -31,43 +33,44 @@
<button
control_name="MuteAudio"
follows="top|right"
- height="16"
- image_selected="icn_speaker-muted_dark.tga"
- image_unselected="icn_speaker_dark.tga"
+ height="18"
+ image_selected="parcel_drk_VoiceNo"
+ image_unselected="parcel_drk_Voice"
is_toggle="true"
layout="topleft"
- left_pad="30"
+ left_pad="16"
name="mute_audio"
picture_style="true"
tab_stop="false"
- top_delta="-1"
- width="25" />
+ top_delta="-2"
+ width="22" />
<check_box
control_name="MuteWhenMinimized"
- height="16"
+ height="15"
initial_value="true"
label="Mute if minimized"
layout="topleft"
- left="165"
+ left="167"
name="mute_when_minimized"
top_pad="5"
width="215" />
<slider
control_name="AudioLevelAmbient"
disabled_control="MuteAudio"
- follows="left|topt"
+ follows="left|top"
height="15"
increment="0.05"
initial_value="0.5"
label="Ambient"
- label_width="125"
+ label_width="160"
layout="topleft"
- left="30"
+ left="0"
name="Wind Volume"
show_text="false"
- top_pad="5"
+ slider_label.halign="right"
+ top_pad="7"
volume="true"
- width="300">
+ width="350">
<slider.commit_callback
function="Pref.setControlFalse"
parameter="MuteAmbient" />
@@ -76,53 +79,54 @@
control_name="MuteAmbient"
disabled_control="MuteAudio"
follows="top|right"
- height="16"
- image_selected="icn_speaker-muted_dark.tga"
- image_unselected="icn_speaker_dark.tga"
+ height="18"
+ image_selected="parcel_drk_VoiceNo"
+ image_unselected="parcel_drk_Voice"
is_toggle="true"
layout="topleft"
- left_pad="30"
+ left_pad="16"
name="mute_wind"
picture_style="true"
tab_stop="false"
- top_delta="-1"
- width="25" />
- <slider
- control_name="AudioLevelSFX"
+ top_delta="-2"
+ width="22" />
+ <slider
+ control_name="AudioLevelUI"
disabled_control="MuteAudio"
follows="left|top"
height="15"
increment="0.05"
initial_value="0.5"
- label="Sounds"
- label_width="125"
+ label="Buttons"
+ label_width="160"
layout="topleft"
- left="30"
- name="SFX Volume"
+ left="0"
+ name="UI Volume"
show_text="false"
- top_pad="5"
+ slider_label.halign="right"
+ top_pad="7"
volume="true"
- width="300">
+ width="350">
<slider.commit_callback
function="Pref.setControlFalse"
- parameter="MuteSounds" />
+ parameter="MuteUI" />
</slider>
<button
- control_name="MuteSounds"
+ control_name="MuteUI"
disabled_control="MuteAudio"
follows="top|right"
- height="16"
- image_selected="icn_speaker-muted_dark.tga"
- image_unselected="icn_speaker_dark.tga"
+ height="18"
+ image_selected="parcel_drk_VoiceNo"
+ image_unselected="parcel_drk_Voice"
is_toggle="true"
layout="topleft"
- left_pad="30"
- name="mute_sfx"
+ left_pad="16"
+ name="mute_ui"
picture_style="true"
tab_stop="false"
- top_delta="-1"
- width="25" />
- <slider
+ top_delta="-2"
+ width="22" />
+ <slider
control_name="AudioLevelMedia"
disabled_control="MuteAudio"
follows="left|top"
@@ -130,14 +134,15 @@
increment="0.05"
initial_value="0.5"
label="Media"
- label_width="125"
+ label_width="160"
layout="topleft"
- left="30"
+ left="0"
name="Media Volume"
show_text="false"
- top_pad="5"
+ slider_label.halign="right"
+ top_pad="7"
volume="true"
- width="300">
+ width="350">
<slider.commit_callback
function="Pref.setControlFalse"
parameter="MuteMedia" />
@@ -146,52 +151,53 @@
control_name="MuteMedia"
disabled_control="MuteAudio"
follows="top|right"
- height="16"
- image_selected="icn_speaker-muted_dark.tga"
- image_unselected="icn_speaker_dark.tga"
+ height="18"
+ image_selected="parcel_drk_VoiceNo"
+ image_unselected="parcel_drk_Voice"
is_toggle="true"
layout="topleft"
- left_pad="30"
+ left_pad="16"
name="mute_media"
picture_style="true"
tab_stop="false"
- top_delta="-1"
- width="25" />
+ top_delta="-2"
+ width="22" />
<slider
- control_name="AudioLevelUI"
+ control_name="AudioLevelSFX"
disabled_control="MuteAudio"
follows="left|top"
height="15"
increment="0.05"
initial_value="0.5"
- label="UI"
- label_width="125"
+ label="Sound effects"
+ label_width="160"
+ slider_label.halign="right"
layout="topleft"
- left="30"
- name="UI Volume"
+ left="0"
+ name="SFX Volume"
show_text="false"
- top_pad="5"
+ top_pad="7"
volume="true"
- width="300">
+ width="350">
<slider.commit_callback
function="Pref.setControlFalse"
- parameter="MuteUI" />
+ parameter="MuteSounds" />
</slider>
<button
- control_name="MuteUI"
+ control_name="MuteSounds"
disabled_control="MuteAudio"
follows="top|right"
- height="16"
- image_selected="icn_speaker-muted_dark.tga"
- image_unselected="icn_speaker_dark.tga"
+ height="18"
+ image_selected="parcel_drk_VoiceNo"
+ image_unselected="parcel_drk_Voice"
is_toggle="true"
layout="topleft"
- left_pad="30"
- name="mute_ui"
+ left_pad="16"
+ name="mute_sfx"
picture_style="true"
tab_stop="false"
- top_delta="-1"
- width="25" />
+ top_delta="-2"
+ width="22" />
<slider
control_name="AudioLevelMusic"
disabled_control="MuteAudio"
@@ -199,15 +205,16 @@
height="15"
increment="0.05"
initial_value="0.5"
- label="Music"
- label_width="125"
+ label="Streaming music"
+ label_width="160"
layout="topleft"
- left="30"
+ left="0"
name="Music Volume"
+ slider_label.halign="right"
show_text="false"
- top_pad="5"
+ top_pad="7"
volume="true"
- width="300">
+ width="350">
<slider.commit_callback
function="Pref.setControlFalse"
parameter="MuteMusic" />
@@ -216,212 +223,206 @@
control_name="MuteMusic"
disabled_control="MuteAudio"
follows="top|right"
- height="16"
- image_selected="icn_speaker-muted_dark.tga"
- image_unselected="icn_speaker_dark.tga"
+ height="18"
+ image_selected="parcel_drk_VoiceNo"
+ image_unselected="parcel_drk_Voice"
is_toggle="true"
layout="topleft"
- left_pad="30"
+ left_pad="16"
name="mute_music"
picture_style="true"
tab_stop="false"
- top_delta="-1"
- width="25" />
+ top_delta="-2"
+ width="22" />
+ <check_box
+ height="16"
+ control_name ="EnableVoiceChat"
+ disabled_control="CmdLineDisableVoice"
+ label="Enable Voice"
+ layout="topleft"
+ left="22"
+ name="enable_voice_check"
+ width="100">
+ </check_box>
<slider
control_name="AudioLevelVoice"
+ enabled_control="EnableVoiceChat"
disabled_control="MuteAudio"
follows="left|top"
height="15"
increment="0.05"
initial_value="0.5"
- label="Voice"
- label_width="125"
+ label="Voice"
+ label_width="60"
layout="topleft"
- left="30"
+ left="100"
name="Voice Volume"
show_text="false"
- top_pad="5"
+ slider_label.halign="right"
+ top_pad="-15"
volume="true"
- width="300">
+ width="250">
<slider.commit_callback
function="Pref.setControlFalse"
parameter="MuteVoice" />
</slider>
<button
control_name="MuteVoice"
+ enabled_control="EnableVoiceChat"
disabled_control="MuteAudio"
follows="top|right"
- height="16"
- image_selected="icn_speaker-muted_dark.tga"
- image_unselected="icn_speaker_dark.tga"
+ height="18"
+ image_selected="parcel_drk_VoiceNo"
+ image_unselected="parcel_drk_Voice"
is_toggle="true"
layout="topleft"
- left_pad="30"
+ left_pad="16"
name="mute_voice"
picture_style="true"
tab_stop="false"
- top_delta="-1"
- width="25" />
+ top_delta="-2"
+ width="22" />
<text
type="string"
length="1"
follows="left|top"
- height="16"
+ height="13"
layout="topleft"
- left="30"
+ left="170"
name="Listen from"
- top_pad="5"
- width="100">
+ width="200">
Listen from:
</text>
- <radio_group
- enabled_control="EnableVoiceChat"
- control_name="VoiceEarLocation"
+ <icon
+ follows="left"
+ height="18"
+ image_name="CameraView_Off"
+ name="camera_icon"
+ mouse_opaque="false"
+ visible="true"
+ width="18" />
+ <icon
+ follows="left"
+ height="18"
+ image_name="Move_Walk_Off"
+ name="avatar_icon"
+ mouse_opaque="false"
+ visible="true"
+ width="18" />
+ <radio_group
+ enabled_control="EnableVoiceChat"
+ control_name="VoiceEarLocation"
draw_border="false"
- height="40"
- layout="topleft"
- left_delta="50"
- name="ear_location"
- top_pad="0"
- width="364">
+ follows="left"
+ left_delta="20"
+ top = "210"
+ width="221"
+ height="38"
+ name="ear_location">
<radio_item
height="16"
- label="Listen from camera position"
- layout="topleft"
- left="3"
+ label="Camera position"
+ left_pad="1"
+ follows="topleft"
name="0"
- top="3"
- width="315" />
+ top_delta="-30"
+ width="200" />
<radio_item
height="16"
- label="Listen from avatar position"
- layout="topleft"
+ follows="topleft"
+ label="Avatar position"
left_delta="0"
name="1"
- top_delta="16"
- width="315" />
+ top_delta="19"
+ width="200" />
</radio_group>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="16"
- layout="topleft"
- left="30"
- name="Sound out/in"
- top_pad="2"
- width="100">
- Sound out/in:
- </text>
<button
control_name="ShowDeviceSettings"
- follows="left|top"
- height="20"
+ follows="left|bottom"
+ height="19"
is_toggle="true"
- label="Device settings"
+ label="Input / Output Devices"
layout="topleft"
- left_delta="55"
+ left="165"
+ top_pad="12"
name="device_settings_btn"
- top_pad="0"
- width="155" />
- <!-- Until new panel is hooked up to code, we need to be able to get to
- the old window to change input devices. James -->
- <button
- follows="left|top"
- label="(Old Window)"
- name="legacy_device_window_btn"
- left_delta="165"
- bottom_delta="0"
- height="20"
- width="120"
- commit_callback.function="Floater.Show"
- commit_callback.parameter="pref_voicedevicesettings"
- />
+ width="190" />
<panel
+ background_visible="true"
+ bg_alpha_color="DkGray"
visiblity_control="ShowDeviceSettings"
border="false"
- follows="top|left"
- height="260"
+ follows="top|left"
+ height="145"
label="DeviceSettings"
layout="topleft"
left="0"
name="Device Settings"
- top_pad="5"
- width="485">
+ width="501">
+ <icon
+ height="18"
+ image_name="Microphone_On"
+ left="80"
+ name="microphone_icon"
+ mouse_opaque="false"
+ top="7"
+ visible="true"
+ width="18" />
<text
type="string"
length="1"
+ font.style="BOLD"
follows="left|top"
height="16"
layout="topleft"
- left="30"
- name="Input device (microphone):"
- top_pad="0"
+ left_pad="3"
+ name="Input"
width="200">
- Input device (microphone):
+ Input
</text>
<combo_box
- height="18"
+ height="19"
layout="topleft"
- left_delta="55"
+ left="165"
max_chars="128"
name="voice_input_device"
- top_pad="2"
- width="225" />
- <text
- type="string"
- length="1"
- follows="left|top"
- height="16"
- layout="topleft"
- left="30"
- name="Output device (speakers):"
- top_pad="5"
- width="200">
- Output device (speakers):
- </text>
- <combo_box
- height="18"
- layout="topleft"
- left_delta="55"
- max_chars="128"
- name="voice_output_device"
- top_pad="2"
- width="225" />
- <text
+ top_pad="0"
+ width="200" />
+ <text
type="string"
length="1"
follows="left|top"
height="16"
layout="topleft"
- left="30"
- name="Input level:"
+ left="165"
+ name="My volume label"
top_pad="10"
width="200">
- Input level
+ My volume:
</text>
- <slider_bar
+ <slider
follows="left|top"
height="17"
increment="0.05"
initial_value="1.0"
layout="topleft"
- left_delta="125"
+ left="160"
max_val="2"
name="mic_volume_slider"
tool_tip="Change the volume using this slider"
- top_delta="-1"
- width="175" />
+ top_pad="0"
+ width="220" />
<text
type="string"
+ text_color="EmphasisColor"
length="1"
follows="left|top"
- height="20"
+ height="18"
layout="topleft"
left_pad="5"
name="wait_text"
- top_delta="1"
- width="200">
+ top_delta="0"
+ width="110">
Please wait
</text>
<locate
@@ -459,16 +460,57 @@
name="bar4"
top_delta="0"
width="20" />
- <text
+ <!-- <text
type="string"
- height="40"
+ height="37"
left="30"
name="voice_intro_text1"
top_pad="-4"
- width="480"
+ width="410"
word_wrap="true">
- Adjust the slider to control how loud you sound to other Residents. To test the input level, simply speak into your microphone.
+ Adjust the slider to control how loud you sound to other people. To test your volume, simply speak into your microphone
+ </text>-->
+ <icon
+ height="18"
+ image_name="parcel_lght_Voice"
+ left="80"
+ name="speaker_icon"
+ mouse_opaque="false"
+ top_pad="-8"
+ visible="true"
+ width="22" />
+ <text
+ font.style="BOLD"
+ type="string"
+ length="1"
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left_pad="0"
+ name="Output"
+ width="200">
+ Output
</text>
+ <combo_box
+ height="19"
+ layout="topleft"
+ left="165"
+ max_chars="128"
+ name="voice_output_device"
+ top_pad="0"
+ width="200" />
+ </panel>
+ <!-- Until new panel is hooked up to code, we need to be able to get to
+ the old window to change input devices. James -->
+ <button
+ follows="left|bottom"
+ label="Old"
+ name="legacy_device_window_btn"
+ height="16"
+ left="20"
+ top="-270"
+ width="40"
+ commit_callback.function="Floater.Show"
+ commit_callback.parameter="pref_voicedevicesettings"
+ />
</panel>
-
-</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml
new file mode 100644
index 0000000000..b21fbc1795
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml
@@ -0,0 +1,594 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ follows="left|right|top|bottom"
+ name="MediaControls"
+ bg_alpha_color="1 1 1 0"
+ height="160"
+ layout="topleft"
+ mouse_opaque="false"
+ width="800">
+ <panel
+ name="media_region"
+ bottom="125"
+ follows="left|right|top|bottom"
+ layout="topleft"
+ left="20"
+ mouse_opaque="false"
+ right="-20"
+ top="20" />
+ <layout_stack
+ follows="left|right|bottom"
+ height="32"
+ layout="topleft"
+ animate="false"
+ left="0"
+ orientation="horizontal"
+ top="96">
+ <!-- outer layout_panels center the inner one -->
+ <layout_panel
+ width="0"
+ layout="topleft"
+ user_resize="false" />
+ <panel
+ name="media_progress_indicator"
+ height="22"
+ layout="topleft"
+ left="0"
+ top="0"
+ auto_resize="false"
+ user_resize="false"
+ min_width="100"
+ width="200">
+ <progress_bar
+ name="media_progress_bar"
+ color_bar="1 1 1 0.96"
+ follows="left|right|top"
+ height="16"
+ layout="topleft"
+ left="0"
+ tool_tip="Media is Loading"/>
+ </panel>
+ <layout_panel
+ width="0"
+ layout="topleft"
+ user_resize="false" />
+ </layout_stack>
+ <layout_stack
+ name="media_controls"
+ follows="left|right"
+ animate="false"
+ height="32"
+ layout="topleft"
+ left="0"
+ orientation="horizontal"
+ top="128">
+ <!-- outer layout_panels center the inner one -->
+ <layout_panel
+ width="0"
+ layout="topleft"
+ user_resize="false" />
+ <layout_panel
+ name="back"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ min_width="22"
+ width="22"
+ top="4">
+ <button
+ auto_resize="false"
+ height="22"
+ image_selected="media_btn_back.png"
+ image_unselected="media_btn_back.png"
+ layout="topleft"
+ tool_tip="Step back"
+ picture_style="true"
+ width="22"
+ top_delta="4">
+ <button.commit_callback
+ function="MediaCtrl.Back" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="fwd"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="10"
+ min_width="17"
+ width="17">
+ <button
+ height="22"
+ image_selected="media_btn_forward.png"
+ image_unselected="media_btn_forward.png"
+ layout="topleft"
+ tool_tip="Step forward"
+ picture_style="true"
+ top_delta="0"
+ min_width="17"
+ width="17">
+ <button.commit_callback
+ function="MediaCtrl.Forward" />
+ </button>
+ </layout_panel>
+<!--
+ <panel
+ height="22"
+ layout="topleft"
+ auto_resize="false"
+ min_width="3"
+ width="3">
+ <icon
+ height="22"
+ image_name="media_panel_divider.png"
+ layout="topleft"
+ top="0"
+ min_width="3"
+ width="3" />
+ </panel>
+-->
+ <layout_panel
+ name="home"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="-2"
+ min_width="22"
+ width="22">
+ <button
+ height="22"
+ image_selected="media_btn_home.png"
+ image_unselected="media_btn_home.png"
+ layout="topleft"
+ tool_tip="Home page"
+ picture_style="true"
+ min_width="22"
+ width="22">
+ <button.commit_callback
+ function="MediaCtrl.Home" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="media_stop"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="2"
+ min_width="22"
+ width="22">
+ <button
+ height="22"
+ image_selected="button_anim_stop.tga"
+ image_unselected="button_anim_stop.tga"
+ layout="topleft"
+ tool_tip="Stop media"
+ picture_style="true"
+ min_width="22"
+ width="22">
+ <button.commit_callback
+ function="MediaCtrl.Stop" />
+ </button>
+ </layout_panel>
+<!--
+ <panel
+ height="22"
+ layout="topleft"
+ auto_resize="false"
+ min_width="3"
+ width="3">
+ <icon
+ height="22"
+ image_name="media_panel_divider.png"
+ layout="topleft"
+ top="0"
+ min_width="3"
+ width="3" />
+ </panel>
+-->
+ <layout_panel
+ name="reload"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="6"
+ min_width="22"
+ width="22">
+ <button
+ height="22"
+ image_selected="media_btn_reload.png"
+ image_unselected="media_btn_reload.png"
+ layout="topleft"
+ tool_tip="Reload"
+ picture_style="true"
+ min_width="22"
+ width="22">
+ <button.commit_callback
+ function="MediaCtrl.Reload" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="stop"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="10"
+ min_width="22"
+ width="22">
+ <button
+ height="22"
+ image_selected="media_btn_stoploading.png"
+ image_unselected="media_btn_stoploading.png"
+ layout="topleft"
+ picture_style="true"
+ tool_tip = "Stop loading"
+ min_width="22"
+ width="22">
+ <button.commit_callback
+ function="MediaCtrl.Stop" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="play"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="14"
+ min_width="22"
+ width="22">
+ <button
+ height="22"
+ image_selected="button_anim_play.tga"
+ image_unselected="button_anim_play.tga"
+ layout="topleft"
+ tool_tip = "Play media"
+ picture_style="true"
+ min_width="22"
+ width="22">
+ <button.commit_callback
+ function="MediaCtrl.Play" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="pause"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="18"
+ min_width="22"
+ width="22">
+ <button
+ height="22"
+ image_selected="button_anim_pause.tga"
+ image_unselected="button_anim_pause.tga"
+ layout="topleft"
+ tool_tip = "Pause media"
+ picture_style="true">
+ <button.commit_callback
+ function="MediaCtrl.Pause" />
+ </button>
+ </layout_panel>
+ <!-- media URL entry -->
+ <layout_panel
+ name="media_address"
+ auto_resize="true"
+ user_resize="false"
+ height="22"
+ follows="left|right|bottom"
+ layout="topleft"
+ width="190"
+ min_width="90">
+ <!--
+ RE-ENABLE THIS WHEN WE HAVE A HISTORY DROP-DOWN AGAIN
+
+<combo_box
+name="media_address_url"
+allow_text_entry="true"
+height="22"
+layout="topleft"
+max_chars="1024"
+tool_tip = "Media URL"
+<combo_box.commit_callback
+function="MediaCtrl.CommitURL" />
+</combo_box>
+ -->
+ <line_editor
+ name="media_address_url"
+ follows="left|right"
+ height="22"
+ top="0"
+ tool_tip="Media URL"
+ text_pad_right="16">
+ <line_editor.commit_callback
+ function="MediaCtrl.CommitURL"/>
+ </line_editor>
+ <layout_stack
+ animate="false"
+ follows="right"
+ width="32"
+ min_width="32"
+ height="16"
+ top="3"
+ orientation="horizontal"
+ left_pad="-38">
+ <icon
+ name="media_whitelist_flag"
+ follows="top|right"
+ height="16"
+ image_name="smicon_warn.tga"
+ layout="topleft"
+ tool_tip="White List enabled"
+ min_width="16"
+ width="16" />
+ <icon
+ name="media_secure_lock_flag"
+ height="16"
+ image_name="inv_item_eyes.tga"
+ layout="topleft"
+ tool_tip="Secured Browsing"
+ min_width="16"
+ width="16" />
+ </layout_stack>
+ </layout_panel>
+ <layout_panel
+ name="media_play_position"
+ auto_resize="true"
+ user_resize="false"
+ follows="left|right|top|bottom"
+ layout="topleft"
+ min_width="100"
+ width="200">
+ <slider_bar
+ name="media_play_slider"
+ follows="left|right|top"
+ height="22"
+ increment="0.05"
+ initial_value="0.5"
+ layout="topleft"
+ tool_tip="Movie play progress"
+ min_width="100"
+ width="200">
+ <slider_bar.commit_callback
+ function="MediaCtrl.JumpProgress" />
+ </slider_bar>
+ </layout_panel>
+ <layout_panel
+ name="media_volume"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ height="24"
+ min_width="24"
+ width="24">
+ <button
+ name="media_volume_button"
+ height="22"
+ image_selected="icn_speaker-muted_dark.tga"
+ image_unselected="icn_speaker_dark.tga"
+ is_toggle="true"
+ layout="topleft"
+ scale_image="false"
+ picture_style="true"
+ tool_tip="Mute This Media"
+ top_delta="22"
+ min_width="24"
+ width="24" >
+ <button.commit_callback
+ function="MediaCtrl.ToggleMute" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="volume_up"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ min_width="20"
+ height="14"
+ width="20">
+ <button
+ top="-3"
+ height="14"
+ image_selected="media_btn_scrollup.png"
+ image_unselected="media_btn_scrollup.png"
+ layout="topleft"
+ tool_tip="Volume up"
+ picture_style="true"
+ scale_image="true"
+ min_width="20"
+ width="20" >
+ <button.commit_callback
+ function="MediaCtrl.CommitVolumeUp" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="volume_down"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ min_width="20"
+ height="14"
+ width="20">
+ <button
+ top="-5"
+ height="14"
+ image_selected="media_btn_scrolldown.png"
+ image_unselected="media_btn_scrolldown.png"
+ layout="topleft"
+ tool_tip="Volume down"
+ picture_style="true"
+ scale_image="true"
+ min_width="20"
+ width="20">
+ <button.commit_callback
+ function="MediaCtrl.CommitVolumeDown" />
+ </button>
+ </layout_panel>
+ <!-- Scroll pad -->
+ <layout_panel
+ name="media_panel_scroll"
+ auto_resize="false"
+ user_resize="false"
+ height="32"
+ follows="left|right|top|bottom"
+ layout="topleft"
+ min_width="32"
+ width="32">
+ <icon
+ height="32"
+ image_name="media_panel_scrollbg.png"
+ layout="topleft"
+ top="0"
+ min_width="32"
+ width="32" />
+ <button
+ name="scrollup"
+ height="8"
+ image_selected="media_btn_scrollup.png"
+ image_unselected="media_btn_scrollup.png"
+ layout="topleft"
+ tool_tip="Scroll up"
+ picture_style="true"
+ scale_image="false"
+ left="12"
+ top_delta="4"
+ min_width="8"
+ width="8" />
+ <button
+ name="scrollleft"
+ height="8"
+ image_selected="media_btn_scrollleft.png"
+ image_unselected="media_btn_scrollleft.png"
+ layout="topleft"
+ left="3"
+ tool_tip="Scroll left"
+ picture_style="true"
+ scale_image="false"
+ top="12"
+ min_width="8"
+ width="8" />
+ <button
+ name="scrollright"
+ height="8"
+ image_selected="media_btn_scrollright.png"
+ image_unselected="media_btn_scrollright.png"
+ layout="topleft"
+ left_pad="9"
+ tool_tip="Scroll right"
+ picture_style="true"
+ scale_image="false"
+ top_delta="0"
+ min_width="8"
+ width="8" />
+ <button
+ name="scrolldown"
+ height="8"
+ image_selected="media_btn_scrolldown.png"
+ image_unselected="media_btn_scrolldown.png"
+ layout="topleft"
+ left="12"
+ tool_tip="Scroll down"
+ picture_style="true"
+ scale_image="false"
+ top="20"
+ min_width="8"
+ width="8" />
+ </layout_panel>
+ <layout_panel
+ name="zoom_frame"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ height="28"
+ min_width="22"
+ width="22">
+ <button
+ height="22"
+ image_selected="media_btn_optimalzoom.png"
+ image_unselected="media_btn_optimalzoom.png"
+ layout="topleft"
+ tool_tip="Zoom"
+ picture_style="true"
+ min_width="22"
+ width="22">
+ <button.commit_callback
+ function="MediaCtrl.Zoom" />
+ </button>
+ </layout_panel>
+<!--
+ <panel
+ height="22"
+ layout="topleft"
+ auto_resize="false"
+ min_width="3"
+ width="3">
+ <icon
+ height="22"
+ image_name="media_panel_divider.png"
+ layout="topleft"
+ top="0"
+ min_width="3"
+ width="3" />
+ </panel>
+-->
+ <layout_panel
+ name="new_window"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ min_width="22"
+ width="22">
+ <button
+ height="22"
+ image_selected="media_btn_newwindow.png"
+ image_unselected="media_btn_newwindow.png"
+ layout="topleft"
+ tool_tip = "Open URL in browser"
+ picture_style="true"
+ top_delta="-3"
+ min_width="24"
+ width="24" >
+ <button.commit_callback
+ function="MediaCtrl.Open" />
+ </button>
+ </layout_panel>
+<!--
+ <panel
+ height="22"
+ layout="topleft"
+ auto_resize="false"
+ min_width="3"
+ width="3">
+ <icon
+ height="22"
+ image_name="media_panel_divider.png"
+ layout="topleft"
+ top="0"
+ min_width="3"
+ width="3" />
+ </panel>
+-->
+ <layout_panel
+ name="close"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ min_width="21"
+ width="21" >
+ <button
+ height="22"
+ image_selected="media_btn_done.png"
+ image_unselected="media_btn_done.png"
+ layout="topleft"
+ tool_tip ="Close media control"
+ picture_style="true"
+ top_delta="-4"
+ width="21" >
+ <button.commit_callback
+ function="MediaCtrl.Close" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ width="0"
+ layout="topleft"
+ user_resize="false" />
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_toast.xml b/indra/newview/skins/default/xui/en/panel_toast.xml
index 894ac07372..200c6622ee 100644
--- a/indra/newview/skins/default/xui/en/panel_toast.xml
+++ b/indra/newview/skins/default/xui/en/panel_toast.xml
@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- All our XML is utf-8 encoded. -->
+<!-- All this does is establish the position of the "close" button on the toast. -->
+
<floater
name="toast"
title=""
visible="false"
layout="topleft"
- width="350"
- height="40"
- left="100"
- top="500"
+ width="305"
+ left="0"
+ top="0"
follows="right|bottom"
- bevel_style="in"
bg_opaque_image="Toast_Background"
bg_alpha_image="Toast_Background"
can_minimize="false"
@@ -20,24 +20,29 @@
can_drag_on_left="false"
can_close="false"
can_dock="false"
+ border_visible = "false"
+ border_drop_shadow_visible = "false"
+ drop_shadow_visible = "false"
+ border = "false"
>
+ <!--
<text
visible="false"
follows="left|top|right|bottom"
font="SansSerifBold"
- height="28"
+ height="40"
layout="topleft"
left="60"
name="toast_text"
word_wrap="true"
text_color="white"
- top="10"
+ top="20"
width="290">
Toast text;
</text>
<icon
- top="4"
+ top="20"
left="10"
width="32"
height="32"
@@ -49,24 +54,24 @@
image_name="notify_tip_icon.tga"
mouse_opaque="true"
name="icon"
- />
+ />-->
<button
layout="topleft"
- top="-5"
- left="335"
- width="20"
- height="20"
+ top="-6"
+ left="293"
+ width="17"
+ height="17"
follows="top|right"
visible="false"
enabled="true"
- mouse_opaque="true"
+ mouse_opaque="false"
name="hide_btn"
label=""
tab_stop="false"
- image_unselected="toast_hide_btn.tga"
- image_disabled="toast_hide_btn.tga"
- image_selected="toast_hide_btn.tga"
- image_hover_selected="toast_hide_btn.tga"
- image_disabled_selected="toast_hide_btn.tga"
+ image_unselected="windows/Toast_CloseBtn.png"
+ image_disabled="windows/Toast_CloseBtn.png"
+ image_selected="windows/Toast_CloseBtn.png"
+ image_hover_selected="windows/Toast_CloseBtn.png"
+ image_disabled_selected="windows/Toast_CloseBtn.png"
/>
</floater>
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 81bc12c33c..4eacd72a7d 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -61,9 +61,7 @@
<string name="TooltipFlagGroupScripts">Group Scripts</string>
<string name="TooltipFlagNoScripts">No Scripts</string>
<string name="TooltipLand">Land:</string>
- <string name="TooltipMustSingleDrop">Only a single item can be dragged here</string>
- <string name="TooltipAltLeft">Alt+&#8592; for previous tab</string>
- <string name="TooltipAltRight">Alt+&#8594; for next tab</string>
+ <string name="TooltipMustSingleDrop">Only a single item can be dragged here</string>
<!-- tooltips for Urls -->
<string name="TooltipHttpUrl">Click to view this web page</string>
@@ -264,10 +262,6 @@
<string name="TrackYourCamera">Track your camera</string>
<string name="ControlYourCamera">Control your camera</string>
- <!-- IM -->
- <string name="IM_logging_string">-- Instant message logging enabled --</string>
- <string name="Unnamed">(Unnamed)</string>
-
<!-- Sim Access labels -->
<string name="SIM_ACCESS_PG">PG</string>
<string name="SIM_ACCESS_MATURE">Mature</string>
@@ -2022,15 +2016,14 @@ this texture in your inventory
<string name="IMTeen">teen</string>
<!-- floater region info -->
+ <!-- The following will replace variable [ALL_ESTATES] in notifications EstateAllowed*, EstateBanned*, EstateManager* -->
<string name="RegionInfoError">error</string>
<string name="RegionInfoAllEstatesOwnedBy">
- all estates
-owned by [OWNER]
+ all estates owned by [OWNER]
</string>
- <string name="RegionInfoAllEstatesYouOwn">all estates you owned</string>
+ <string name="RegionInfoAllEstatesYouOwn">all estates that you own</string>
<string name="RegionInfoAllEstatesYouManage">
- all estates that
-you managed for [OWNER]
+ all estates that you manage for [OWNER]
</string>
<string name="RegionInfoAllowedResidents">Allowed residents: ([ALLOWEDAGENTS], max [MAXACCESS])</string>
<string name="RegionInfoAllowedGroups">Allowed groups: ([ALLOWEDGROUPS], max [MAXACCESS])</string>
@@ -2884,7 +2877,14 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
Failed to start viewer
</string>
- <!-- IM system messages -->
+ <!-- IM system messages -->
+ <string name="IM_logging_string">-- Instant message logging enabled --</string>
+ <string name="IM_typing_start_string">[NAME] is typing...</string>
+ <string name="Unnamed">(Unnamed)</string>
+ <string name="IM_moderated_chat_label">(Moderated: Voices off by default)</string>
+ <string name="IM_unavailable_text_label">Text chat is not available for this call.</string>
+
+
<string name="ringing-im">
Joining Voice Chat...
</string>
diff --git a/indra/newview/skins/default/xui/en/widgets/chat_history.xml b/indra/newview/skins/default/xui/en/widgets/chat_history.xml
index b72d59524e..ea6997ebd5 100644
--- a/indra/newview/skins/default/xui/en/widgets/chat_history.xml
+++ b/indra/newview/skins/default/xui/en/widgets/chat_history.xml
@@ -4,8 +4,8 @@
message_separator="panel_chat_separator.xml"
left_text_pad="10"
right_text_pad="15"
- left_widget_pad="5"
- rigth_widget_pad="10"
+ left_widget_pad="0"
+ right_widget_pad="10"
max_length="2147483647"
enabled="false"
track_bottom="true"
diff --git a/indra/newview/skins/default/xui/en/widgets/gesture_combo_box.xml b/indra/newview/skins/default/xui/en/widgets/gesture_combo_box.xml
index 89e442baec..ab4ad94089 100644
--- a/indra/newview/skins/default/xui/en/widgets/gesture_combo_box.xml
+++ b/indra/newview/skins/default/xui/en/widgets/gesture_combo_box.xml
@@ -23,7 +23,8 @@
image_selected="DropDown_Selected"
image_disabled="DropDown_Disabled"
image_disabled_selected="DropDown_Disabled_Selected" />
- <gesture_combo_box.combo_list bg_writeable_color="MenuDefaultBgColor" />
+ <gesture_combo_box.combo_list bg_writeable_color="MenuDefaultBgColor"
+ scroll_bar_bg_visible="true" />
<gesture_combo_box.combo_editor name="Combo Text Entry"
select_on_focus="true"
font="SansSerifSmall" />
diff --git a/indra/newview/skins/default/xui/en/widgets/tab_container.xml b/indra/newview/skins/default/xui/en/widgets/tab_container.xml
index 2fe5f517a2..7d10df1af7 100644
--- a/indra/newview/skins/default/xui/en/widgets/tab_container.xml
+++ b/indra/newview/skins/default/xui/en/widgets/tab_container.xml
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<tab_container tab_min_width="60"
tab_max_width="150"
+ font_halign="left"
tab_height="16">
<first_tab tab_top_image_unselected="TabTop_Left_Off"
tab_top_image_selected="TabTop_Left_Selected"