diff options
27 files changed, 490 insertions, 121 deletions
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 5c2b3236f6..8323bfc12f 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -873,13 +873,12 @@ BOOL LLView::handleToolTip(S32 x, S32 y, MASK mask) // allow "scrubbing" over ui by showing next tooltip immediately // if previous one was still visible F32 timeout = LLToolTipMgr::instance().toolTipVisible() - ? LLUI::sSettingGroups["config"]->getF32( "ToolTipFastDelay" ) - : LLUI::sSettingGroups["config"]->getF32( "ToolTipDelay" ); + ? LLUI::sSettingGroups["config"]->getF32( "ToolTipFastDelay" ) + : LLUI::sSettingGroups["config"]->getF32( "ToolTipDelay" ); LLToolTipMgr::instance().show(LLToolTip::Params() - .message(tooltip) - .sticky_rect(calcScreenRect()) - .delay_time(timeout)); - + .message(tooltip) + .sticky_rect(calcScreenRect()) + .delay_time(timeout)); handled = TRUE; } diff --git a/indra/llui/llview.h b/indra/llui/llview.h index 1c35349510..15b85a6418 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -67,7 +67,6 @@ const BOOL NOT_MOUSE_OPAQUE = FALSE; const U32 GL_NAME_UI_RESERVED = 2; - // maintains render state during traversal of UI tree class LLViewDrawContext { diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index b94c33587b..ec1562a4c1 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -197,6 +197,7 @@ set(viewer_SOURCE_FILES llfloaterbuycurrencyhtml.cpp llfloaterbuyland.cpp llfloatercamera.cpp + llfloaterchatvoicevolume.cpp llfloatercolorpicker.cpp llfloaterconversationlog.cpp llfloaterconversationpreview.cpp @@ -781,6 +782,7 @@ set(viewer_HEADER_FILES llfloaterbuycurrencyhtml.h llfloaterbuyland.h llfloatercamera.h + llfloaterchatvoicevolume.h llfloatercolorpicker.h llfloaterconversationlog.h llfloaterconversationpreview.h diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 42a0376774..a76dbcac53 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -897,6 +897,12 @@ void LLAvatarActions::inviteToGroup(const LLUUID& id) } } +// static +void LLAvatarActions::viewChatHistory(const LLUUID& id) +{ + LLFloaterReg::showInstance("preview_conversation", id, true); +} + //== private methods ======================================================================================== // static diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index 473b9cecc3..6e60f624ad 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -218,6 +218,11 @@ public: */ static void buildResidentsString(const std::vector<LLAvatarName> avatar_names, std::string& residents_string); + /** + * Opens the chat history for avatar + */ + static void viewChatHistory(const LLUUID& id); + static std::set<LLUUID> getInventorySelectedUUIDs(); private: diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index f587ef8428..265f77365f 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -294,8 +294,8 @@ void LLConversationItemParticipant::buildContextMenu(LLMenuGL& menu, U32 flags) void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_name) { - mName = av_name.mUsername; - mDisplayName = av_name.mDisplayName; + mName = (av_name.mUsername.empty() ? av_name.mDisplayName : av_name.mUsername); + mDisplayName = (av_name.mDisplayName.empty() ? av_name.mUsername : av_name.mDisplayName); mNeedsRefresh = true; if (mParent) { diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index a4733bb693..d4eb551f7a 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -30,10 +30,12 @@ #include "llconversationview.h" #include <boost/bind.hpp> +#include "llagentdata.h" #include "llconversationmodel.h" #include "llimconversation.h" #include "llimfloatercontainer.h" #include "llfloaterreg.h" +#include "llgroupiconctrl.h" #include "lluictrlfactory.h" // @@ -43,6 +45,30 @@ static LLDefaultChildRegistry::Register<LLConversationViewSession> r_conversatio const LLColor4U DEFAULT_WHITE(255, 255, 255); +class LLNearbyVoiceClientStatusObserver : public LLVoiceClientStatusObserver +{ +public: + + LLNearbyVoiceClientStatusObserver(LLConversationViewSession* conv) + : conversation(conv) + {} + + virtual void onChange(EStatusType status, const std::string &channelURI, bool proximal) + { + if (conversation + && status != STATUS_JOINING + && status != STATUS_LEFT_CHANNEL + && LLVoiceClient::getInstance()->voiceEnabled() + && LLVoiceClient::getInstance()->isVoiceWorking()) + { + conversation->showVoiceIndicator(); + } + } + +private: + LLConversationViewSession* conversation; +}; + LLConversationViewSession::Params::Params() : container() {} @@ -51,20 +77,86 @@ LLConversationViewSession::LLConversationViewSession(const LLConversationViewSes LLFolderViewFolder(p), mContainer(p.container), mItemPanel(NULL), - mSessionTitle(NULL) + mCallIconLayoutPanel(NULL), + mSessionTitle(NULL), + mSpeakingIndicator(NULL), + mVoiceClientObserver(NULL), + mMinimizedMode(false) { } +LLConversationViewSession::~LLConversationViewSession() +{ + mActiveVoiceChannelConnection.disconnect(); + + if(LLVoiceClient::instanceExists() && mVoiceClientObserver) + { + LLVoiceClient::getInstance()->removeObserver(mVoiceClientObserver); + } +} + BOOL LLConversationViewSession::postBuild() { LLFolderViewItem::postBuild(); mItemPanel = LLUICtrlFactory::getInstance()->createFromFile<LLPanel>("panel_conversation_list_item.xml", NULL, LLPanel::child_registry_t::instance()); - addChild(mItemPanel); + mCallIconLayoutPanel = mItemPanel->getChild<LLPanel>("call_icon_panel"); mSessionTitle = mItemPanel->getChild<LLTextBox>("conversation_title"); + mActiveVoiceChannelConnection = LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLConversationViewSession::onCurrentVoiceSessionChanged, this, _1)); + mSpeakingIndicator = getChild<LLOutputMonitorCtrl>("speaking_indicatorn"); + + LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(getViewModelItem()); + if (vmi) + { + switch(vmi->getType()) + { + case LLConversationItem::CONV_PARTICIPANT: + case LLConversationItem::CONV_SESSION_1_ON_1: + { + LLIMModel::LLIMSession* session= LLIMModel::instance().findIMSession(vmi->getUUID()); + if (session) + { + LLAvatarIconCtrl* icon = mItemPanel->getChild<LLAvatarIconCtrl>("avatar_icon"); + icon->setVisible(true); + icon->setValue(session->mOtherParticipantID); + mSpeakingIndicator->setSpeakerId(gAgentID, session->mSessionID, true); + } + break; + } + case LLConversationItem::CONV_SESSION_AD_HOC: + { + LLGroupIconCtrl* icon = mItemPanel->getChild<LLGroupIconCtrl>("group_icon"); + icon->setVisible(true); + mSpeakingIndicator->setSpeakerId(gAgentID, vmi->getUUID(), true); + } + case LLConversationItem::CONV_SESSION_GROUP: + { + LLGroupIconCtrl* icon = mItemPanel->getChild<LLGroupIconCtrl>("group_icon"); + icon->setVisible(true); + icon->setValue(vmi->getUUID()); + mSpeakingIndicator->setSpeakerId(gAgentID, vmi->getUUID(), true); + break; + } + case LLConversationItem::CONV_SESSION_NEARBY: + { + LLIconCtrl* icon = mItemPanel->getChild<LLIconCtrl>("nearby_chat_icon"); + icon->setVisible(true); + mSpeakingIndicator->setSpeakerId(gAgentID, LLUUID::null, true); + if(LLVoiceClient::instanceExists()) + { + LLNearbyVoiceClientStatusObserver* mVoiceClientObserver = new LLNearbyVoiceClientStatusObserver(this); + LLVoiceClient::getInstance()->addObserver(mVoiceClientObserver); + } + break; + } + default: + break; + } + } + refresh(); return TRUE; @@ -77,15 +169,18 @@ void LLConversationViewSession::draw() const LLFolderViewItem::Params& default_params = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>(); const BOOL show_context = (getRoot() ? getRoot()->getShowSelectionContext() : FALSE); - // update the rotation angle of open folder arrow - updateLabelRotation(); + // we don't draw the open folder arrow in minimized mode + if (!mMinimizedMode) + { + // update the rotation angle of open folder arrow + updateLabelRotation(); - drawOpenFolderArrow(default_params, sFgColor); + drawOpenFolderArrow(default_params, sFgColor); + } // draw highlight for selected items drawHighlight(show_context, true, sHighlightBgColor, sFocusOutlineColor, sMouseOverColor); - // draw children if root folder, or any other folder that is open or animating to closed state bool draw_children = getRoot() == static_cast<LLFolderViewFolder*>(this) || isOpen() @@ -110,7 +205,8 @@ void LLConversationViewSession::draw() // virtual S32 LLConversationViewSession::arrange(S32* width, S32* height) { - LLRect rect(getIndentation() + mArrowSize, + S32 h_pad = getIndentation() + mArrowSize; + LLRect rect(mMinimizedMode ? getLocalRect().mLeft : h_pad, getLocalRect().mTop, getLocalRect().mRight, getLocalRect().mTop - getItemHeight()); @@ -119,6 +215,16 @@ S32 LLConversationViewSession::arrange(S32* width, S32* height) return LLFolderViewFolder::arrange(width, height); } +// virtual +void LLConversationViewSession::toggleOpen() +{ + // conversations should not be opened while in minimized mode + if (!mMinimizedMode) + { + LLFolderViewFolder::toggleOpen(); + } +} + void LLConversationViewSession::selectItem() { @@ -140,6 +246,18 @@ void LLConversationViewSession::selectItem() LLFolderViewItem::selectItem(); } +void LLConversationViewSession::toggleMinimizedMode(bool is_minimized) +{ + mMinimizedMode = is_minimized; + + // hide the layout stack which contains all item's child widgets + // except for the icon which we display in minimized mode + getChild<LLView>("conversation_item_stack")->setVisible(!mMinimizedMode); + + S32 h_pad = getIndentation() + mArrowSize; + mItemPanel->translate(mMinimizedMode ? -h_pad : h_pad, 0); +} + void LLConversationViewSession::setVisibleIfDetached(BOOL visible) { // Do this only if the conversation floater has been torn off (i.e. no multi floater host) and is not minimized @@ -171,6 +289,14 @@ LLConversationViewParticipant* LLConversationViewSession::findParticipant(const return (iter == getItemsEnd() ? NULL : participant); } +void LLConversationViewSession::showVoiceIndicator() +{ + if (LLVoiceChannel::getCurrentVoiceChannel()->getSessionID().isNull()) + { + mCallIconLayoutPanel->setVisible(true); + } +} + void LLConversationViewSession::refresh() { // Refresh the session view from its model data @@ -188,6 +314,25 @@ void LLConversationViewSession::refresh() LLFolderViewFolder::refresh(); } +void LLConversationViewSession::onCurrentVoiceSessionChanged(const LLUUID& session_id) +{ + LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(getViewModelItem()); + + if (vmi) + { + bool is_active = vmi->getUUID() == session_id; + bool is_nearby = vmi->getType() == LLConversationItem::CONV_SESSION_NEARBY; + + if (is_nearby) + { + mSpeakingIndicator->setSpeakerId(is_active ? gAgentID : LLUUID::null); + } + + mSpeakingIndicator->switchIndicator(is_active); + mCallIconLayoutPanel->setVisible(is_active); + } +} + // // Implementation of conversations list participant (avatar) widgets // diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 0b98c34c73..c81c70b456 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -38,6 +38,8 @@ class LLIMFloaterContainer; class LLConversationViewSession; class LLConversationViewParticipant; +class LLVoiceClientStatusObserver; + // Implementation of conversations list session widgets class LLConversationViewSession : public LLFolderViewFolder @@ -57,7 +59,7 @@ protected: LLIMFloaterContainer* mContainer; public: - virtual ~LLConversationViewSession( void ) { } + virtual ~LLConversationViewSession(); virtual void selectItem(); /*virtual*/ BOOL postBuild(); @@ -65,14 +67,31 @@ public: /*virtual*/ S32 arrange(S32* width, S32* height); + /*virtual*/ void toggleOpen(); + + void toggleMinimizedMode(bool is_minimized); + void setVisibleIfDetached(BOOL visible); LLConversationViewParticipant* findParticipant(const LLUUID& participant_id); + void showVoiceIndicator(); + virtual void refresh(); private: - LLPanel* mItemPanel; - LLTextBox* mSessionTitle; + + void onCurrentVoiceSessionChanged(const LLUUID& session_id); + + LLPanel* mItemPanel; + LLPanel* mCallIconLayoutPanel; + LLTextBox* mSessionTitle; + LLOutputMonitorCtrl* mSpeakingIndicator; + + bool mMinimizedMode; + + LLVoiceClientStatusObserver* mVoiceClientObserver; + + boost::signals2::connection mActiveVoiceChannelConnection; }; // Implementation of conversations list participant (avatar) widgets diff --git a/indra/newview/llfloaterchatvoicevolume.cpp b/indra/newview/llfloaterchatvoicevolume.cpp new file mode 100644 index 0000000000..3c76a3a43c --- /dev/null +++ b/indra/newview/llfloaterchatvoicevolume.cpp @@ -0,0 +1,44 @@ +/** + * @file llfloaterchatvoicevolume.cpp + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloaterchatvoicevolume.h" + +LLFloaterChatVoiceVolume::LLFloaterChatVoiceVolume(const LLSD& key) +: LLInspect(key) +{ +} + +void LLFloaterChatVoiceVolume::onOpen(const LLSD& key) +{ + LLInspect::onOpen(key); + LLUI::positionViewNearMouse(this); +} + +LLFloaterChatVoiceVolume::~LLFloaterChatVoiceVolume() +{ + LLTransientFloaterMgr::getInstance()->removeControlView(this); +}; diff --git a/indra/newview/llfloaterchatvoicevolume.h b/indra/newview/llfloaterchatvoicevolume.h new file mode 100644 index 0000000000..61ad92b6da --- /dev/null +++ b/indra/newview/llfloaterchatvoicevolume.h @@ -0,0 +1,44 @@ +/** + * @file llfloaterchatvoicevolume.h + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LLFLOATERCHATVOICEVOLUME_H_ +#define LLFLOATERCHATVOICEVOLUME_H_ + +#include "llinspect.h" +#include "lltransientfloatermgr.h" + +class LLFloaterChatVoiceVolume : public LLInspect, LLTransientFloater +{ +public: + + LLFloaterChatVoiceVolume(const LLSD& key); + virtual ~LLFloaterChatVoiceVolume(); + + virtual void onOpen(const LLSD& key); + + /*virtual*/ LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::GLOBAL; } +}; + +#endif /* LLFLOATERCHATVOICEVOLUME_H_ */ diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 43adfdfd08..d11504d312 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -582,13 +582,14 @@ void LLIMFloater::onParticipantsListChanged(LLUICtrl* ctrl) build_names_string(temp_uuids, ui_title); updateSessionName(ui_title, ui_title); } - } +} -//static -LLIMFloater* LLIMFloater::addToIMContainer(const LLUUID& session_id) +void LLIMFloater::addToHost(const LLUUID& session_id, const bool force) { - if (!gIMMgr->hasSession(session_id)) - return NULL; + if (!LLIMConversation::isChatMultiTab() || !gIMMgr->hasSession(session_id)) + { + return; + } // Test the existence of the floater before we try to create it bool exist = findInstance(session_id); @@ -612,19 +613,22 @@ LLIMFloater* LLIMFloater::addToIMContainer(const LLUUID& session_id) } } - if (floater_container && floater_container->getVisible()) + if (force) { - floater->openFloater(floater->getKey()); - floater->setVisible(TRUE); - } - else - { - floater->setVisible(FALSE); + if (floater_container && floater_container->getVisible()) + { + floater->openFloater(floater->getKey()); + floater->setVisible(TRUE); + } + else + { + floater->setVisible(FALSE); + } } } - return floater; } + //static LLIMFloater* LLIMFloater::show(const LLUUID& session_id) { @@ -1323,23 +1327,6 @@ void LLIMFloater::onIMChicletCreated( const LLUUID& session_id ) { LLIMFloater::addToHost(session_id); } -void LLIMFloater::addToHost(const LLUUID& session_id) - { - if (LLIMConversation::isChatMultiTab()) -{ - LLIMFloaterContainer* im_box = LLIMFloaterContainer::findInstance(); - if (!im_box) - { - im_box = LLIMFloaterContainer::getInstance(); - } - - if (im_box && !LLIMFloater::findInstance(session_id)) - { - LLIMFloater* new_tab = LLIMFloater::getInstance(session_id); - im_box->addFloater(new_tab, FALSE, LLTabContainer::END); - } - } -} boost::signals2::connection LLIMFloater::setIMFloaterShowedCallback(const floater_showed_signal_t::slot_type& cb) { diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 489e430b26..5ed1d1ab35 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -71,14 +71,13 @@ public: static LLIMFloater* findInstance(const LLUUID& session_id); static LLIMFloater* getInstance(const LLUUID& session_id); - static void addToHost(const LLUUID& session_id); + static void addToHost(const LLUUID& session_id, const bool force = false); // LLFloater overrides /*virtual*/ void onClose(bool app_quitting); /*virtual*/ void setDocked(bool docked, bool pop_on_undock = true); // Make IM conversion visible and update the message history static LLIMFloater* show(const LLUUID& session_id); - static LLIMFloater* addToIMContainer(const LLUUID& session_id); // Toggle panel specified by session_id // Returns true iff panel became visible diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 58d2020801..d25a195f33 100755..100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -90,13 +90,13 @@ LLIMFloaterContainer::~LLIMFloaterContainer() void LLIMFloaterContainer::sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) { - LLIMFloater::addToIMContainer(session_id); + LLIMFloater::addToHost(session_id, true); addConversationListItem(session_id); } void LLIMFloaterContainer::sessionVoiceOrIMStarted(const LLUUID& session_id) { - LLIMFloater::addToIMContainer(session_id); + LLIMFloater::addToHost(session_id, true); addConversationListItem(session_id); } @@ -137,6 +137,7 @@ BOOL LLIMFloaterContainer::postBuild() p.listener = base_item; p.view_model = &mConversationViewModel; p.root = NULL; + p.use_ellipses = true; p.options_menu = "menu_conversation.xml"; mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); @@ -164,8 +165,7 @@ BOOL LLIMFloaterContainer::postBuild() collapseMessagesPane(gSavedPerAccountSettings.getBOOL("ConversationsMessagePaneCollapsed")); collapseConversationsPane(gSavedPerAccountSettings.getBOOL("ConversationsListPaneCollapsed")); - LLAvatarNameCache::addUseDisplayNamesCallback( - boost::bind(&LLIMConversation::processChatHistoryStyleUpdate)); + LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLIMConversation::processChatHistoryStyleUpdate)); if (! mMessagesPane->isCollapsed()) { @@ -182,8 +182,11 @@ BOOL LLIMFloaterContainer::postBuild() mInitialized = true; - // Add callback: we'll take care of view updates on idle + // Add callbacks: + // We'll take care of view updates on idle gIdleCallbacks.addFunction(idle, this); + // When display name option change, we need to reload all participant names + LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLIMFloaterContainer::processParticipantsStyleUpdate, this)); return TRUE; } @@ -227,8 +230,8 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp, floaterp->mCloseSignal.connect(boost::bind(&LLIMFloaterContainer::onCloseFloater, this, session_id)); } else - { - LLUUID avatar_id = LLIMModel::getInstance()->getOtherParticipantID(session_id); + { LLUUID avatar_id = session_id.notNull()? + LLIMModel::getInstance()->getOtherParticipantID(session_id) : LLUUID(); LLAvatarIconCtrl::Params icon_params; icon_params.avatar_id = avatar_id; @@ -336,6 +339,37 @@ void LLIMFloaterContainer::setMinimized(BOOL b) } } +// Update all participants in the conversation lists +void LLIMFloaterContainer::processParticipantsStyleUpdate() +{ + // On each session in mConversationsItems + for (conversations_items_map::iterator it_session = mConversationsItems.begin(); it_session != mConversationsItems.end(); it_session++) + { + // Get the current session descriptors + LLConversationItem* session_model = it_session->second; + // Iterate through each model participant child + LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = session_model->getChildrenBegin(); + LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = session_model->getChildrenEnd(); + while (current_participant_model != end_participant_model) + { + LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model); + // Get the avatar name for this participant id from the cache and update the model + LLUUID participant_id = participant_model->getUUID(); + LLAvatarName av_name; + LLAvatarNameCache::get(participant_id,&av_name); + // Avoid updating the model though if the cache is still waiting for its first update + if (!av_name.mDisplayName.empty()) + { + participant_model->onAvatarNameCache(av_name); + } + // Bind update to the next cache name signal + LLAvatarNameCache::get(participant_id, boost::bind(&LLConversationItemParticipant::onAvatarNameCache, participant_model, _2)); + // Next participant + current_participant_model++; + } + } +} + // static void LLIMFloaterContainer::idle(void* user_data) { @@ -347,7 +381,6 @@ void LLIMFloaterContainer::idle(void* user_data) { self->setNearbyDistances(); } - self->mConversationsRoot->update(); } @@ -438,6 +471,7 @@ void LLIMFloaterContainer::setVisible(BOOL visible) // *TODO: find a way to move this to XML as a default panel or something like that LLSD name("nearby_chat"); LLFloaterReg::toggleInstanceOrBringToFront(name); + LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat")->addToHost(); } } @@ -505,6 +539,22 @@ void LLIMFloaterContainer::collapseConversationsPane(bool collapse) S32 collapsed_width = mConversationsPane->getMinDim(); updateState(collapse, gSavedPerAccountSettings.getS32("ConversationsListPaneWidth") - collapsed_width); + + for (conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); + widget_it != mConversationsWidgets.end(); ++widget_it) + { + LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(widget_it->second); + if (widget) + { + widget->toggleMinimizedMode(collapse); + + // force closing all open conversations when collapsing to minimized state + if (collapse) + { + widget->setOpen(false); + } +} + } } void LLIMFloaterContainer::updateState(bool collapse, S32 delta_width) @@ -856,56 +906,6 @@ bool LLIMFloaterContainer::checkContextMenuItem(const LLSD& userdata) return false; } -void LLIMFloaterContainer::repositioningWidgets() -{ - if (!mInitialized) - { - return; - } - - if (!mConversationsPane->isCollapsed()) - { - S32 list_width = (mConversationsPane->getRect()).getWidth(); - gSavedPerAccountSettings.setS32("ConversationsListPaneWidth", list_width); - } - LLRect panel_rect = mConversationsListPanel->getRect(); - S32 item_height = 16; - int index = 0; - for (conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin(); - widget_it != mConversationsWidgets.end(); - widget_it++) - { - LLFolderViewFolder* widget = dynamic_cast<LLFolderViewFolder*>(widget_it->second); - widget->setVisible(TRUE); - widget->setRect(LLRect(0, - panel_rect.getHeight() - item_height*index, - panel_rect.getWidth(), - panel_rect.getHeight() - item_height*(index+1))); - index++; - // Reposition the children as well - // Merov : This is highly suspiscious but gets the debug hack to work. This needs to be revised though. - if (widget->getItemsCount() != 0) - { - BOOL is_open = widget->isOpen(); - widget->setOpen(TRUE); - LLFolderViewFolder::items_t::const_iterator current = widget->getItemsBegin(); - LLFolderViewFolder::items_t::const_iterator end = widget->getItemsEnd(); - while (current != end) - { - LLFolderViewItem* item = (*current); - item->setVisible(TRUE); - item->setRect(LLRect(0, - panel_rect.getHeight() - item_height*index, - panel_rect.getWidth(), - panel_rect.getHeight() - item_height*(index+1))); - index++; - current++; - } - widget->setOpen(is_open); - } - } -} - void LLIMFloaterContainer::setConvItemSelect(const LLUUID& session_id) { LLFolderViewItem* widget = mConversationsWidgets[session_id]; @@ -1018,6 +1018,9 @@ void LLIMFloaterContainer::addConversationListItem(const LLUUID& uuid) setConvItemSelect(uuid); + // set the widget to minimized mode if conversations pane is collapsed + widget->toggleMinimizedMode(mConversationsPane->isCollapsed()); + return; } diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index cc2d0ce6ab..49a41e5cdd 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -96,11 +96,11 @@ private: void onNewMessageReceived(const LLSD& data); void onExpandCollapseButtonClicked(); + void processParticipantsStyleUpdate(); void collapseConversationsPane(bool collapse); void updateState(bool collapse, S32 delta_width); - void repositioningWidgets(); void onAddButtonClicked(); void onAvatarPicked(const uuid_vec_t& ids); diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 6e692adf2a..a8d99ad7de 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -442,8 +442,9 @@ void LLInventoryPanel::modelChanged(U32 mask) handled = true; if (model_item && view_item && viewmodel_item) { + const LLUUID& idp = viewmodel_item->getUUID(); view_item->destroyView(); - removeItemID(viewmodel_item->getUUID()); + removeItemID(idp); } view_item = buildNewViews(item_id); viewmodel_item = diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 71c4938ae9..4b35092f2d 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -110,6 +110,7 @@ BOOL LLNearbyChat::postBuild() mInputEditor->setKeystrokeCallback(boost::bind(&onChatBoxKeystroke, _1, this)); mInputEditor->setFocusLostCallback(boost::bind(&onChatBoxFocusLost, _1, this)); mInputEditor->setFocusReceivedCallback(boost::bind(&LLNearbyChat::onChatBoxFocusReceived, this)); + mInputEditor->setLabel(LLTrans::getString("NearbyChatTitle")); // mOutputMonitor = getChild<LLOutputMonitorCtrl>("chat_zone_indicator"); // mOutputMonitor->setVisible(FALSE); @@ -121,8 +122,6 @@ BOOL LLNearbyChat::postBuild() // it is used for show the item's name in the conversations list setTitle(LLTrans::getString("NearbyChatTitle")); - addToHost(); - //for menu LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index 096e714981..4a9a50d96a 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -74,7 +74,8 @@ LLOutputMonitorCtrl::LLOutputMonitorCtrl(const LLOutputMonitorCtrl::Params& p) mSpeakerId(p.speaker_id), mIsAgentControl(false), mIsSwitchDirty(false), - mShouldSwitchOn(false) + mShouldSwitchOn(false), + mShowParticipantsSpeaking(false) { //static LLUIColor output_monitor_muted_color = LLUIColorTable::instance().getColor("OutputMonitorMutedColor", LLColor4::orange); //static LLUIColor output_monitor_overdriven_color = LLUIColorTable::instance().getColor("OutputMonitorOverdrivenColor", LLColor4::red); @@ -157,6 +158,24 @@ void LLOutputMonitorCtrl::draw() } } + if ((mPower == 0.f && !mIsTalking) && mShowParticipantsSpeaking) + { + std::set<LLUUID> participant_uuids; + LLVoiceClient::instance().getParticipantList(participant_uuids); + std::set<LLUUID>::const_iterator part_it = participant_uuids.begin(); + + F32 power = 0; + for (; part_it != participant_uuids.end(); ++part_it) + { + power = LLVoiceClient::instance().getCurrentPower(*part_it); + if (power) + { + mPower = power; + break; + } + } + } + LLPointer<LLUIImage> icon; if (mIsMuted) { @@ -245,15 +264,19 @@ void LLOutputMonitorCtrl::draw() // virtual BOOL LLOutputMonitorCtrl::handleMouseUp(S32 x, S32 y, MASK mask) { - if (mSpeakerId != gAgentID) + if (mSpeakerId != gAgentID && !mShowParticipantsSpeaking) { LLFloaterReg::showInstance("floater_voice_volume", LLSD().with("avatar_id", mSpeakerId)); } + else if(mShowParticipantsSpeaking) + { + LLFloaterReg::showInstance("chat_voice", LLSD()); + } return TRUE; } -void LLOutputMonitorCtrl::setSpeakerId(const LLUUID& speaker_id, const LLUUID& session_id/* = LLUUID::null*/) +void LLOutputMonitorCtrl::setSpeakerId(const LLUUID& speaker_id, const LLUUID& session_id/* = LLUUID::null*/, bool show_other_participants_speaking /* = false */) { if (speaker_id.isNull() && mSpeakerId.notNull()) { @@ -268,6 +291,7 @@ void LLOutputMonitorCtrl::setSpeakerId(const LLUUID& speaker_id, const LLUUID& s LLSpeakingIndicatorManager::unregisterSpeakingIndicator(mSpeakerId, this); } + mShowParticipantsSpeaking = show_other_participants_speaking; mSpeakerId = speaker_id; LLSpeakingIndicatorManager::registerSpeakingIndicator(mSpeakerId, this, session_id); diff --git a/indra/newview/lloutputmonitorctrl.h b/indra/newview/lloutputmonitorctrl.h index 7b02e84744..1fa6ef41f8 100644 --- a/indra/newview/lloutputmonitorctrl.h +++ b/indra/newview/lloutputmonitorctrl.h @@ -82,6 +82,8 @@ public: void setIsTalking(bool val) { mIsTalking = val; } + void setShowParticipantsSpeaking(bool show) { mShowParticipantsSpeaking = show; } + /** * Sets avatar UUID to interact with voice channel. * @@ -90,7 +92,7 @@ public: * If this parameter is set registered indicator will be shown only in voice channel * which has the same session id (EXT-5562). */ - void setSpeakerId(const LLUUID& speaker_id, const LLUUID& session_id = LLUUID::null); + void setSpeakerId(const LLUUID& speaker_id, const LLUUID& session_id = LLUUID::null, bool show_other_participants_speaking = false); //called by mute list virtual void onChange(); @@ -132,6 +134,7 @@ private: bool mIsAgentControl; bool mIsMuted; bool mIsTalking; + bool mShowParticipantsSpeaking; LLPointer<LLUIImage> mImageMute; LLPointer<LLUIImage> mImageOff; LLPointer<LLUIImage> mImageOn; diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp index c9eebe24d3..899771f3b9 100644 --- a/indra/newview/llpanelpeoplemenus.cpp +++ b/indra/newview/llpanelpeoplemenus.cpp @@ -69,6 +69,7 @@ LLContextMenu* NearbyMenu::createMenu() registrar.add("Avatar.Pay", boost::bind(&LLAvatarActions::pay, id)); registrar.add("Avatar.BlockUnblock", boost::bind(&LLAvatarActions::toggleBlock, id)); registrar.add("Avatar.InviteToGroup", boost::bind(&LLAvatarActions::inviteToGroup, id)); + registrar.add("Avatar.Calllog", boost::bind(&LLAvatarActions::viewChatHistory, id)); enable_registrar.add("Avatar.EnableItem", boost::bind(&NearbyMenu::enableContextMenuItem, this, _2)); enable_registrar.add("Avatar.CheckItem", boost::bind(&NearbyMenu::checkContextMenuItem, this, _2)); diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 927ee8f380..4cd5ecc754 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -50,6 +50,7 @@ #include "llfloaterbump.h" #include "llfloaterbvhpreview.h" #include "llfloatercamera.h" +#include "llfloaterchatvoicevolume.h" #include "llfloaterconversationlog.h" #include "llfloaterconversationpreview.h" #include "llfloaterdeleteenvpreset.h" @@ -192,6 +193,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("bumps", "floater_bumps.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBump>); LLFloaterReg::add("camera", "floater_camera.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCamera>); + LLFloaterReg::add("chat_voice", "floater_voice_chat_volume.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterChatVoiceVolume>); LLFloaterReg::add("nearby_chat", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNearbyChat>); LLFloaterReg::add("compile_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCompileQueue>); LLFloaterReg::add("conversation", "floater_conversation_log.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterConversationLog>); diff --git a/indra/newview/skins/default/textures/icons/nearby_chat_icon.png b/indra/newview/skins/default/textures/icons/nearby_chat_icon.png Binary files differnew file mode 100644 index 0000000000..7c3ad40381 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/nearby_chat_icon.png diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 47b0c12fa0..a124041565 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -363,6 +363,8 @@ with the same filename but different name <texture name="NavBar_BG_NoFav_Bevel" file_name="navbar/NavBar_BG_NoFav_Bevel.png" preload="true" scale.left="1" scale.top="1" scale.right="0" scale.bottom="0" /> <texture name="NavBar_BG_NoNav_Bevel" file_name="navbar/NavBar_BG_NoNav_Bevel.png" preload="true" scale.left="1" scale.top="1" scale.right="0" scale.bottom="0" /> + <texture name="Nearby_chat_icon" file_name="icons/nearby_chat_icon.png" preload="false" /> + <texture name="Notices_Unread" file_name="bottomtray/Notices_Unread.png" preload="true" /> <texture name="NoEntryLines" file_name="world/NoEntryLines.png" use_mips="true" preload="false" /> diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index d23ff28fd0..590ce45c33 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -11,6 +11,7 @@ save_rect="true" save_visibility="true" single_instance="true" + reuse_instance="true" title="CONVERSATIONS" width="680"> <string diff --git a/indra/newview/skins/default/xui/en/floater_voice_chat_volume.xml b/indra/newview/skins/default/xui/en/floater_voice_chat_volume.xml new file mode 100644 index 0000000000..5c71fd3bc6 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_voice_chat_volume.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> + +<floater + legacy_header_height="25" + bevel_style="in" + bg_opaque_image="Inspector_Background" + can_close="false" + can_minimize="false" + height="90" + layout="topleft" + name="floater_voice_volume" + single_instance="true" + sound_flags="0" + title="VOICE CHAT VOLUME" + visible="true" + width="245"> + <slider + control_name="AudioLevelVoice" + disabled_control="MuteAudio" + follows="left|top" + height="16" + increment="0.025" + initial_value="0.5" + label="Voice Chat" + label_width="50" + layout="topleft" + left="15" + top="50" + name="chat_voice_volume" + show_text="false" + slider_label.halign="right" + volume="true" + width="200"> + </slider> + <button + control_name="MuteVoice" + disabled_control="MuteAudio" + follows="top|left" + height="16" + image_selected="AudioMute_Off" + image_unselected="Audio_Off" + is_toggle="true" + layout="topleft" + left_pad="5" + name="mute_audio" + tab_stop="false" + width="16" /> +</floater>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/menu_people_friends_view.xml b/indra/newview/skins/default/xui/en/menu_people_friends_view.xml index eab7b8c085..dde9432867 100644 --- a/indra/newview/skins/default/xui/en/menu_people_friends_view.xml +++ b/indra/newview/skins/default/xui/en/menu_people_friends_view.xml @@ -40,4 +40,12 @@ function="CheckControl" parameter="FriendsListShowPermissions" /> </menu_item_check> + <menu_item_check name="view_conversation" label="View Conversation Log..."> + <menu_item_check.on_check + function="Floater.Visible" + parameter="conversation" /> + <menu_item_check.on_click + function="Floater.Toggle" + parameter="conversation" /> + </menu_item_check> </toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby.xml b/indra/newview/skins/default/xui/en/menu_people_nearby.xml index b7c9ab1fe3..8014e81469 100644 --- a/indra/newview/skins/default/xui/en/menu_people_nearby.xml +++ b/indra/newview/skins/default/xui/en/menu_people_nearby.xml @@ -37,6 +37,14 @@ </menu_item_call> <menu_item_separator /> <menu_item_call + label="View chat history..." + layout="topleft" + name="Chat history"> + <menu_item_call.on_click + function="Avatar.Calllog" /> + </menu_item_call> + <menu_item_separator /> + <menu_item_call label="Add Friend" layout="topleft" name="Add Friend"> @@ -101,5 +109,5 @@ function="Avatar.EnableItem" parameter="can_block" /> </menu_item_check> - + <menu_item_separator /> </context_menu> diff --git a/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml b/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml index 375ea79ebe..56056ed560 100644 --- a/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_conversation_list_item.xml @@ -13,13 +13,33 @@ layout="topleft" left="5" top="2" + visible="false" width="20" /> + <group_icon + follows="top|left" + height="20" + default_icon_name="Generic_Group" + layout="topleft" + left="5" + top="2" + visible="false" + width="20" /> + <icon + follows="top|left" + height="20" + image_name="Nearby_chat_icon" + layout="topleft" + left="5" + name="nearby_chat_icon" + top="2" + visible="false" + width="20"/> <layout_stack animate="false" follows="all" height="24" layout="topleft" - left_pad="5" + left="30" mouse_opaque="false" name="conversation_item_stack" orientation="horizontal" @@ -36,7 +56,7 @@ <icon height="20" follows="top|right|left" - image_name="Conv_toolbar_hang_up" + image_name="Conv_toolbar_open_call" layout="topleft" left="0" name="selected_icon" @@ -70,7 +90,7 @@ layout="topleft" left_pad="5" mouse_opaque="true" - name="speaking_indicator" + name="speaking_indicatorn" visible="false" width="20" /> </layout_panel> |