diff options
Diffstat (limited to 'indra')
43 files changed, 489 insertions, 314 deletions
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 17aecaf32f..47db990a37 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1009,6 +1009,16 @@ void LLTextBase::draw() void LLTextBase::setColor( const LLColor4& c ) { mFgColor = c; + //textsegments have own style property , + //so we have to update it also to apply changes, EXT-4433 + for(segment_set_t::iterator it = mSegments.begin(); it != mSegments.end(); it++) + { + LLTextSegment* segment = it->get(); + if(segment) + { + segment->setColor(mFgColor); + } + } } //virtual diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index c29a3a0035..72d2e1aba0 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10314,6 +10314,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>VoiceDefaultInternalLevel</key> + <map> + <key>Comment</key> + <string>Internal level of voice set by default. Is equivalent to 0.5 (from 0.0-1.0 range) external voice level (internal = 400 * external^2).</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>100</integer> + </map> <key>VoiceEarLocation</key> <map> <key>Comment</key> diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 40c9bb6afa..bb14c41cec 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -263,18 +263,9 @@ bool LLAvatarActions::isCalling(const LLUUID &id) } //static -bool LLAvatarActions::canCall(const LLUUID &id) +bool LLAvatarActions::canCall() { - // For now we do not need to check whether passed UUID is ID of agent's friend. - // Use common check of Voice Client state. - { - // don't need to check online/offline status because "usual resident" (resident that is not a friend) - // can be only ONLINE. There is no way to see "usual resident" in OFFLINE status. If we see "usual - // resident" it automatically means that the resident is ONLINE. So to make a call to the "usual resident" - // we need to check only that "our" voice is enabled. - return LLVoiceClient::voiceEnabled(); - } - + return LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking(); } // static diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index a4504ae679..ebfd40b796 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -129,10 +129,10 @@ public: static bool isCalling(const LLUUID &id); /** - * @return true if call to the resident can be made (resident is online and voice is enabled) + * @return true if call to the resident can be made */ - static bool canCall(const LLUUID &id); + static bool canCall(); /** * Invite avatar to a group. */ diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index 66ab32f3e8..2bcd097717 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -440,17 +440,17 @@ LLAvatarListItem::icon_color_map_t& LLAvatarListItem::getItemIconColorMap() // static void LLAvatarListItem::initChildrenWidths(LLAvatarListItem* avatar_item) { + //speaking indicator width + padding + S32 speaking_indicator_width = avatar_item->getRect().getWidth() - avatar_item->mSpeakingIndicator->getRect().mLeft; + //profile btn width + padding - S32 profile_btn_width = avatar_item->getRect().getWidth() - avatar_item->mProfileBtn->getRect().mLeft; + S32 profile_btn_width = avatar_item->mSpeakingIndicator->getRect().mLeft - avatar_item->mProfileBtn->getRect().mLeft; //info btn width + padding S32 info_btn_width = avatar_item->mProfileBtn->getRect().mLeft - avatar_item->mInfoBtn->getRect().mLeft; - //speaking indicator width + padding - S32 speaking_indicator_width = avatar_item->mInfoBtn->getRect().mLeft - avatar_item->mSpeakingIndicator->getRect().mLeft; - // last interaction time textbox width + padding - S32 last_interaction_time_width = avatar_item->mSpeakingIndicator->getRect().mLeft - avatar_item->mLastInteractionTime->getRect().mLeft; + S32 last_interaction_time_width = avatar_item->mInfoBtn->getRect().mLeft - avatar_item->mLastInteractionTime->getRect().mLeft; // icon width + padding S32 icon_width = avatar_item->mAvatarName->getRect().mLeft - avatar_item->mAvatarIcon->getRect().mLeft; @@ -462,9 +462,9 @@ void LLAvatarListItem::initChildrenWidths(LLAvatarListItem* avatar_item) sChildrenWidths[--index] = icon_width; sChildrenWidths[--index] = 0; // for avatar name we don't need its width, it will be calculated as "left available space" sChildrenWidths[--index] = last_interaction_time_width; - sChildrenWidths[--index] = speaking_indicator_width; sChildrenWidths[--index] = info_btn_width; sChildrenWidths[--index] = profile_btn_width; + sChildrenWidths[--index] = speaking_indicator_width; } void LLAvatarListItem::updateChildren() diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h index 479a4833cb..61c0a8660e 100644 --- a/indra/newview/llavatarlistitem.h +++ b/indra/newview/llavatarlistitem.h @@ -129,9 +129,9 @@ private: * @see updateChildren() */ typedef enum e_avatar_item_child { + ALIC_SPEAKER_INDICATOR, ALIC_PROFILE_BUTTON, ALIC_INFO_BUTTON, - ALIC_SPEAKER_INDICATOR, ALIC_INTERACTION_TIME, ALIC_NAME, ALIC_ICON, diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp index d4c8adadc6..d9df537e03 100644 --- a/indra/newview/llcallfloater.cpp +++ b/indra/newview/llcallfloater.cpp @@ -43,6 +43,7 @@ #include "llavatariconctrl.h" #include "llavatarlist.h" #include "llbottomtray.h" +#include "lldraghandle.h" #include "llimfloater.h" #include "llfloaterreg.h" #include "llparticipantlist.h" @@ -158,6 +159,11 @@ BOOL LLCallFloater::postBuild() connectToChannel(LLVoiceChannel::getCurrentVoiceChannel()); + setIsChrome(true); + //chrome="true" hides floater caption + if (mDragHandle) + mDragHandle->setTitleVisible(TRUE); + return TRUE; } diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index a46cd84b60..d6a7edee5b 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -550,8 +550,8 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_ if (mLastFromName == chat.mFromName && mLastFromID == chat.mFromID && mLastMessageTime.notNull() - && (new_message_time.secondsSinceEpoch() - mLastMessageTime.secondsSinceEpoch()) < 60.0 - ) + && (new_message_time.secondsSinceEpoch() - mLastMessageTime.secondsSinceEpoch()) < 60.0 + && mLastMessageTimeStr.size() == chat.mTimeStr.size()) //*HACK to distinguish between current and previous chat session's histories { view = getSeparator(); p.top_pad = mTopSeparatorPad; @@ -585,6 +585,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const bool use_plain_text_ mLastFromName = chat.mFromName; mLastFromID = chat.mFromID; mLastMessageTime = new_message_time; + mLastMessageTimeStr = chat.mTimeStr; } std::string message = irc_me ? chat.mText.substr(3) : chat.mText; diff --git a/indra/newview/llchathistory.h b/indra/newview/llchathistory.h index f2d403f639..c2c60e60cf 100644 --- a/indra/newview/llchathistory.h +++ b/indra/newview/llchathistory.h @@ -125,6 +125,8 @@ class LLChatHistory : public LLUICtrl std::string mLastFromName; LLUUID mLastFromID; LLDate mLastMessageTime; + std::string mLastMessageTimeStr; + std::string mMessageHeaderFilename; std::string mMessageSeparatorFilename; diff --git a/indra/newview/llfloatergroups.cpp b/indra/newview/llfloatergroups.cpp index 29f415bd43..c71764c2e5 100644 --- a/indra/newview/llfloatergroups.cpp +++ b/indra/newview/llfloatergroups.cpp @@ -75,7 +75,7 @@ LLFloaterGroupPicker::~LLFloaterGroupPicker() void LLFloaterGroupPicker::setPowersMask(U64 powers_mask) { mPowersMask = powers_mask; - postBuild(); + init_group_list(getChild<LLScrollListCtrl>("group list"), gAgent.getGroupID(), mPowersMask); } diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index fc036cb354..60c15c253d 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -1435,6 +1435,7 @@ BOOL LLPanelPreference::postBuild() media_enabled_ctrl->set(enabled); media_enabled_ctrl->setTentative(!(video_enabled == music_enabled == media_enabled)); getChild<LLCheckBoxCtrl>("autoplay_enabled")->setEnabled(enabled); + getChild<LLCheckBoxCtrl>("voice_call_friends_only_check")->setCommitCallback(boost::bind(&showFriendsOnlyWarning, _1, _2)); } apply(); @@ -1485,6 +1486,14 @@ void LLPanelPreference::saveSettings() } } +void LLPanelPreference::showFriendsOnlyWarning(LLUICtrl* checkbox, const LLSD& value) +{ + if (checkbox && checkbox->getValue()) + { + LLNotificationsUtil::add("FriendsAndGroupsOnly"); + } +} + void LLPanelPreference::cancel() { for (control_values_map_t::iterator iter = mSavedValues.begin(); diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 6f382620ee..8b02a4049d 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -166,6 +166,9 @@ public: virtual void saveSettings(); private: + //for "Only friends and groups can call or IM me" + static void showFriendsOnlyWarning(LLUICtrl*, const LLSD&); + typedef std::map<LLControlVariable*, LLSD> control_values_map_t; control_values_map_t mSavedValues; diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 2efae0c8db..4a1eb51dbe 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -324,7 +324,7 @@ void LLFloaterReporter::setFromAvatar(const LLUUID& avatar_id, const std::string std::string avatar_link = LLSLURL::buildCommand("agent", mObjectID, "inspect"); childSetText("owner_name", avatar_link); - childSetText("object_name", avatar_name); // name + childSetText("object_name", avatar_name); childSetText("abuser_name_edit", avatar_name); } diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index e75d35bea4..e01709aa3a 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -48,6 +48,7 @@ #include "lltextutil.h" #include "llviewercontrol.h" // for gSavedSettings #include "llviewermenu.h" // for gMenuHolder +#include "llvoiceclient.h" static LLDefaultChildRegistry::Register<LLGroupList> r("group_list"); S32 LLGroupListItem::sIconWidth = 0; @@ -271,6 +272,9 @@ bool LLGroupList::onContextMenuItemEnable(const LLSD& userdata) if (userdata.asString() == "activate") return gAgent.getGroupID() != selected_group_id; + if (userdata.asString() == "call") + return LLVoiceClient::voiceEnabled()&&gVoiceClient->voiceWorking(); + return real_group_selected; } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index c2a7969c0d..32b0cbff38 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -1680,6 +1680,7 @@ void LLOutgoingCallDialog::show(const LLSD& key) case LLVoiceChannel::STATE_ERROR : getChild<LLTextBox>("noanswer")->setVisible(true); getChild<LLButton>("Cancel")->setVisible(false); + setCanClose(true); mLifetimeTimer.start(); break; case LLVoiceChannel::STATE_HUNG_UP : @@ -1692,6 +1693,7 @@ void LLOutgoingCallDialog::show(const LLSD& key) getChild<LLTextBox>("nearby")->setVisible(true); } getChild<LLButton>("Cancel")->setVisible(false); + setCanClose(true); mLifetimeTimer.start(); } diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp index 7ee4c64f8f..c1666f5666 100644 --- a/indra/newview/llmutelist.cpp +++ b/indra/newview/llmutelist.cpp @@ -52,23 +52,15 @@ #include <boost/tokenizer.hpp> -#include "llcrc.h" -#include "lldir.h" #include "lldispatcher.h" -#include "llsdserialize.h" #include "llxfermanager.h" -#include "message.h" #include "llagent.h" #include "llviewergenericmessage.h" // for gGenericDispatcher -#include "llviewerwindow.h" #include "llworld.h" //for particle system banning -#include "llchat.h" #include "llimpanel.h" #include "llimview.h" #include "llnotifications.h" -#include "lluistring.h" -#include "llviewerobject.h" #include "llviewerobjectlist.h" #include "lltrans.h" @@ -219,61 +211,17 @@ LLMuteList* LLMuteList::getInstance() // LLMuteList() //----------------------------------------------------------------------------- LLMuteList::LLMuteList() : - mIsLoaded(FALSE), - mUserVolumesLoaded(FALSE) + mIsLoaded(FALSE) { gGenericDispatcher.addHandler("emptymutelist", &sDispatchEmptyMuteList); } -void LLMuteList::loadUserVolumes() -{ - // call once, after LLDir::setLindenUserDir() has been called - if (mUserVolumesLoaded) - return; - mUserVolumesLoaded = TRUE; - - // load per-resident voice volume information - // conceptually, this is part of the mute list information, although it is only stored locally - std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "volume_settings.xml"); - - LLSD settings_llsd; - llifstream file; - file.open(filename); - if (file.is_open()) - { - LLSDSerialize::fromXML(settings_llsd, file); - } - - for (LLSD::map_const_iterator iter = settings_llsd.beginMap(); - iter != settings_llsd.endMap(); ++iter) - { - mUserVolumeSettings.insert(std::make_pair(LLUUID(iter->first), (F32)iter->second.asReal())); - } -} - //----------------------------------------------------------------------------- // ~LLMuteList() //----------------------------------------------------------------------------- LLMuteList::~LLMuteList() { - // If we quit from the login screen we will not have an SL account - // name. Don't try to save, otherwise we'll dump a file in - // C:\Program Files\SecondLife\ or similar. JC - std::string user_dir = gDirUtilp->getLindenUserDir(); - if (!user_dir.empty()) - { - std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "volume_settings.xml"); - LLSD settings_llsd; - - for(user_volume_map_t::iterator iter = mUserVolumeSettings.begin(); iter != mUserVolumeSettings.end(); ++iter) - { - settings_llsd[iter->first.asString()] = iter->second; - } - llofstream file; - file.open(filename); - LLSDSerialize::toPrettyXML(settings_llsd, file); - } } BOOL LLMuteList::isLinden(const std::string& name) const @@ -715,8 +663,6 @@ BOOL LLMuteList::isMuted(const LLUUID& id, const std::string& name, U32 flags) c //----------------------------------------------------------------------------- void LLMuteList::requestFromServer(const LLUUID& agent_id) { - loadUserVolumes(); - std::string agent_id_string; std::string filename; agent_id.toString(agent_id_string); @@ -751,26 +697,6 @@ void LLMuteList::cache(const LLUUID& agent_id) } } -void LLMuteList::setSavedResidentVolume(const LLUUID& id, F32 volume) -{ - // store new value in volume settings file - mUserVolumeSettings[id] = volume; -} - -F32 LLMuteList::getSavedResidentVolume(const LLUUID& id) -{ - const F32 DEFAULT_VOLUME = 0.5f; - - user_volume_map_t::iterator found_it = mUserVolumeSettings.find(id); - if (found_it != mUserVolumeSettings.end()) - { - return found_it->second; - } - //FIXME: assumes default, should get this from somewhere - return DEFAULT_VOLUME; -} - - //----------------------------------------------------------------------------- // Static message handlers //----------------------------------------------------------------------------- diff --git a/indra/newview/llmutelist.h b/indra/newview/llmutelist.h index 409b637bf2..e1e81a24b4 100644 --- a/indra/newview/llmutelist.h +++ b/indra/newview/llmutelist.h @@ -127,12 +127,7 @@ public: // call this method on logout to save everything. void cache(const LLUUID& agent_id); - void setSavedResidentVolume(const LLUUID& id, F32 volume); - F32 getSavedResidentVolume(const LLUUID& id); - private: - void loadUserVolumes(); - BOOL loadFromFile(const std::string& filename); BOOL saveToFile(const std::string& filename); @@ -179,12 +174,8 @@ private: observer_set_t mObservers; BOOL mIsLoaded; - BOOL mUserVolumesLoaded; friend class LLDispatchEmptyMuteList; - - typedef std::map<LLUUID, F32> user_volume_map_t; - user_volume_map_t mUserVolumeSettings; }; class LLMuteListObserver diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index a7c1e73328..0a8d020b4f 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -101,6 +101,11 @@ BOOL LLNearbyChat::postBuild() getDockTongue(), LLDockControl::TOP, boost::bind(&LLNearbyChat::getAllowedRect, this, _1))); } + setIsChrome(true); + //chrome="true" hides floater caption + if (mDragHandle) + mDragHandle->setTitleVisible(TRUE); + return true; } diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index 85e95ca1d6..fe5b20813a 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -165,6 +165,8 @@ BOOL LLPanelAvatarNotes::postBuild() resetControls(); resetData(); + gVoiceClient->addObserver((LLVoiceClientStatusObserver*)this); + return TRUE; } @@ -337,6 +339,8 @@ LLPanelAvatarNotes::~LLPanelAvatarNotes() if(getAvatarId().notNull()) { LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this); + if(LLVoiceClient::getInstance()) + LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this); } } @@ -346,6 +350,17 @@ void LLPanelAvatarNotes::changed(U32 mask) childSetEnabled("teleport", LLAvatarTracker::instance().isBuddyOnline(getAvatarId())); } +// virtual +void LLPanelAvatarNotes::onChange(EStatusType status, const std::string &channelURI, bool proximal) +{ + if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL) + { + return; + } + + childSetEnabled("call", LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking()); +} + void LLPanelAvatarNotes::setAvatarId(const LLUUID& id) { if(id.notNull()) @@ -437,7 +452,6 @@ void LLPanelProfileTab::updateButtons() bool enable_map_btn = is_avatar_online && gAgent.isGodlike() || is_agent_mappable(getAvatarId()); childSetEnabled("show_on_map_btn", enable_map_btn); - childSetEnabled("call", LLAvatarActions::canCall(getAvatarId())); } ////////////////////////////////////////////////////////////////////////// @@ -485,6 +499,8 @@ BOOL LLPanelAvatarProfile::postBuild() pic = getChild<LLTextureCtrl>("real_world_pic"); pic->setFallbackImageName("default_profile_picture.j2c"); + gVoiceClient->addObserver((LLVoiceClientStatusObserver*)this); + resetControls(); resetData(); @@ -568,8 +584,6 @@ void LLPanelAvatarProfile::processProfileProperties(const LLAvatarData* avatar_d fillPartnerData(avatar_data); - fillOnlineStatus(avatar_data); - fillAccountStatus(avatar_data); } @@ -637,21 +651,6 @@ void LLPanelAvatarProfile::fillPartnerData(const LLAvatarData* avatar_data) } } -void LLPanelAvatarProfile::fillOnlineStatus(const LLAvatarData* avatar_data) -{ - bool online = avatar_data->flags & AVATAR_ONLINE; - if(LLAvatarActions::isFriend(avatar_data->avatar_id)) - { - // Online status NO could be because they are hidden - // If they are a friend, we may know the truth! - online = LLAvatarTracker::instance().isBuddyOnline(avatar_data->avatar_id); - } - childSetValue("online_status", online ? - "Online" : "Offline"); - childSetColor("online_status", online ? - LLColor4::green : LLColor4::red); -} - void LLPanelAvatarProfile::fillAccountStatus(const LLAvatarData* avatar_data) { LLStringUtil::format_map_t args; @@ -757,6 +756,8 @@ LLPanelAvatarProfile::~LLPanelAvatarProfile() if(getAvatarId().notNull()) { LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this); + if(LLVoiceClient::getInstance()) + LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this); } } @@ -766,6 +767,17 @@ void LLPanelAvatarProfile::changed(U32 mask) childSetEnabled("teleport", LLAvatarTracker::instance().isBuddyOnline(getAvatarId())); } +// virtual +void LLPanelAvatarProfile::onChange(EStatusType status, const std::string &channelURI, bool proximal) +{ + if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL) + { + return; + } + + childSetEnabled("call", LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking()); +} + void LLPanelAvatarProfile::setAvatarId(const LLUUID& id) { if(id.notNull()) diff --git a/indra/newview/llpanelavatar.h b/indra/newview/llpanelavatar.h index 22efa5dc35..ce59f1e93d 100644 --- a/indra/newview/llpanelavatar.h +++ b/indra/newview/llpanelavatar.h @@ -36,6 +36,7 @@ #include "llpanel.h" #include "llavatarpropertiesprocessor.h" #include "llcallingcard.h" +#include "llvoiceclient.h" class LLComboBox; class LLLineEditor; @@ -122,6 +123,7 @@ private: class LLPanelAvatarProfile : public LLPanelProfileTab , public LLFriendObserver + , public LLVoiceClientStatusObserver { public: LLPanelAvatarProfile(); @@ -134,6 +136,10 @@ public: */ virtual void changed(U32 mask); + // Implements LLVoiceClientStatusObserver::onChange() to enable the call + // button when voice is available + /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal); + /*virtual*/ void setAvatarId(const LLUUID& id); /** @@ -172,11 +178,6 @@ protected: virtual void fillPartnerData(const LLAvatarData* avatar_data); /** - * Fills Avatar's online status. - */ - virtual void fillOnlineStatus(const LLAvatarData* avatar_data); - - /** * Fills account status. */ virtual void fillAccountStatus(const LLAvatarData* avatar_data); @@ -257,6 +258,7 @@ private: class LLPanelAvatarNotes : public LLPanelProfileTab , public LLFriendObserver + , public LLVoiceClientStatusObserver { public: LLPanelAvatarNotes(); @@ -269,6 +271,10 @@ public: */ virtual void changed(U32 mask); + // Implements LLVoiceClientStatusObserver::onChange() to enable the call + // button when voice is available + /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal); + /*virtual*/ void onOpen(const LLSD& key); /*virtual*/ BOOL postBuild(); diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp index c30ef3221d..1d447a22d7 100644 --- a/indra/newview/llpanelgroup.cpp +++ b/indra/newview/llpanelgroup.cpp @@ -101,6 +101,8 @@ LLPanelGroup::LLPanelGroup() LLPanelGroup::~LLPanelGroup() { LLGroupMgr::getInstance()->removeObserver(this); + if(LLVoiceClient::getInstance()) + LLVoiceClient::getInstance()->removeObserver(this); } void LLPanelGroup::onOpen(const LLSD& key) @@ -188,6 +190,8 @@ BOOL LLPanelGroup::postBuild() if(panel_general) panel_general->setupCtrls(this); + + gVoiceClient->addObserver(this); return TRUE; } @@ -300,6 +304,17 @@ void LLPanelGroup::changed(LLGroupChange gc) update(gc); } +// virtual +void LLPanelGroup::onChange(EStatusType status, const std::string &channelURI, bool proximal) +{ + if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL) + { + return; + } + + childSetEnabled("btn_call", LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking()); +} + void LLPanelGroup::notifyObservers() { changed(GC_ALL); @@ -356,6 +371,13 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id) for(std::vector<LLPanelGroupTab* >::iterator it = mTabs.begin();it!=mTabs.end();++it) (*it)->setGroupID(group_id); + LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mID); + if(gdatap) + { + childSetValue("group_name", gdatap->mName); + childSetToolTip("group_name",gdatap->mName); + } + LLButton* button_apply = findChild<LLButton>("btn_apply"); LLButton* button_refresh = findChild<LLButton>("btn_refresh"); LLButton* button_create = findChild<LLButton>("btn_create"); @@ -457,17 +479,6 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id) } reposButtons(); - - LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mID); - - if(gdatap) - { - childSetValue("group_name", gdatap->mName); - childSetToolTip("group_name",gdatap->mName); - - //group data is already present, call update manually - update(GC_ALL); - } } bool LLPanelGroup::apply(LLPanelGroupTab* tab) diff --git a/indra/newview/llpanelgroup.h b/indra/newview/llpanelgroup.h index 7ea5e67b44..8c84695677 100644 --- a/indra/newview/llpanelgroup.h +++ b/indra/newview/llpanelgroup.h @@ -35,6 +35,7 @@ #include "llgroupmgr.h" #include "llpanel.h" #include "lltimer.h" +#include "llvoiceclient.h" struct LLOfferInfo; @@ -47,7 +48,8 @@ class LLAgent; class LLPanelGroup : public LLPanel, - public LLGroupMgrObserver + public LLGroupMgrObserver, + public LLVoiceClientStatusObserver { public: LLPanelGroup(); @@ -64,6 +66,10 @@ public: // Group manager observer trigger. virtual void changed(LLGroupChange gc); + // Implements LLVoiceClientStatusObserver::onChange() to enable the call + // button when voice is available + /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal); + void showNotice(const std::string& subject, const std::string& message, const bool& has_inventory, diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp index a334eb9d68..ff1e43b526 100644 --- a/indra/newview/llpanelimcontrolpanel.cpp +++ b/indra/newview/llpanelimcontrolpanel.cpp @@ -64,21 +64,52 @@ void LLPanelChatControlPanel::onOpenVoiceControlsClicked() LLFloaterReg::showInstance("voice_controls"); } +void LLPanelChatControlPanel::onChange(EStatusType status, const std::string &channelURI, bool proximal) +{ + if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL) + { + return; + } + + updateCallButton(); +} + void LLPanelChatControlPanel::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state) { updateButtons(new_state >= LLVoiceChannel::STATE_CALL_STARTED); } +void LLPanelChatControlPanel::updateCallButton() +{ + // hide/show call button + bool voice_enabled = LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking(); + + LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(mSessionId); + if (!session) return; + + bool session_initialized = session->mSessionInitialized; + bool callback_enabled = session->mCallBackEnabled; + + BOOL enable_connect = session_initialized + && voice_enabled + && callback_enabled; + childSetEnabled("call_btn", enable_connect); +} + void LLPanelChatControlPanel::updateButtons(bool is_call_started) { childSetVisible("end_call_btn_panel", is_call_started); childSetVisible("voice_ctrls_btn_panel", is_call_started); childSetVisible("call_btn_panel", ! is_call_started); + updateCallButton(); + } LLPanelChatControlPanel::~LLPanelChatControlPanel() { mVoiceChannelStateChangeConnection.disconnect(); + if(LLVoiceClient::getInstance()) + LLVoiceClient::getInstance()->removeObserver(this); } BOOL LLPanelChatControlPanel::postBuild() @@ -87,26 +118,9 @@ BOOL LLPanelChatControlPanel::postBuild() childSetAction("end_call_btn", boost::bind(&LLPanelChatControlPanel::onEndCallButtonClicked, this)); childSetAction("voice_ctrls_btn", boost::bind(&LLPanelChatControlPanel::onOpenVoiceControlsClicked, 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; + gVoiceClient->addObserver(this); - bool session_initialized = session->mSessionInitialized; - bool callback_enabled = session->mCallBackEnabled; - - BOOL enable_connect = session_initialized - && voice_enabled - && callback_enabled; - childSetEnabled("call_btn", enable_connect); - - LLPanel::draw(); + return TRUE; } void LLPanelChatControlPanel::setSessionId(const LLUUID& session_id) @@ -266,6 +280,8 @@ void LLPanelGroupControlPanel::draw() // Need to resort the participant list if it's in sort by recent speaker order. if (mParticipantList) mParticipantList->updateRecentSpeakersOrder(); + //* TODO: find better way to properly enable call button for group and remove this call from draw() + updateCallButton(); LLPanelChatControlPanel::draw(); } diff --git a/indra/newview/llpanelimcontrolpanel.h b/indra/newview/llpanelimcontrolpanel.h index 25fdf944c9..3ab505a084 100644 --- a/indra/newview/llpanelimcontrolpanel.h +++ b/indra/newview/llpanelimcontrolpanel.h @@ -39,7 +39,9 @@ class LLParticipantList; -class LLPanelChatControlPanel : public LLPanel +class LLPanelChatControlPanel + : public LLPanel + , public LLVoiceClientStatusObserver { public: LLPanelChatControlPanel() : @@ -47,15 +49,21 @@ public: ~LLPanelChatControlPanel(); virtual BOOL postBuild(); - virtual void draw(); void onCallButtonClicked(); void onEndCallButtonClicked(); void onOpenVoiceControlsClicked(); + // Implements LLVoiceClientStatusObserver::onChange() to enable the call + // button when voice is available + /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal); + virtual void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state); void updateButtons(bool is_call_started); + + // Enables/disables call button depending on voice availability + void updateCallButton(); virtual void setSessionId(const LLUUID& session_id); const LLUUID& getSessionId() { return mSessionId; } diff --git a/indra/newview/llpanelme.cpp b/indra/newview/llpanelme.cpp index ece93125b3..0f0fb4b94e 100644 --- a/indra/newview/llpanelme.cpp +++ b/indra/newview/llpanelme.cpp @@ -198,8 +198,6 @@ void LLPanelMyProfileEdit::processProfileProperties(const LLAvatarData* avatar_d { fillCommonData(avatar_data); - fillOnlineStatus(avatar_data); - fillPartnerData(avatar_data); fillAccountStatus(avatar_data); diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index c14b282488..b01cdcc832 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -462,6 +462,9 @@ LLPanelPeople::~LLPanelPeople() delete mFriendListUpdater; delete mRecentListUpdater; + if(LLVoiceClient::getInstance()) + LLVoiceClient::getInstance()->removeObserver(this); + LLView::deleteViewByHandle(mGroupPlusMenuHandle); LLView::deleteViewByHandle(mNearbyViewSortMenuHandle); LLView::deleteViewByHandle(mFriendsViewSortMenuHandle); @@ -612,6 +615,8 @@ BOOL LLPanelPeople::postBuild() if(recent_view_sort) mRecentViewSortMenuHandle = recent_view_sort->getHandle(); + gVoiceClient->addObserver(this); + // call this method in case some list is empty and buttons can be in inconsistent state updateButtons(); @@ -621,6 +626,17 @@ BOOL LLPanelPeople::postBuild() return TRUE; } +// virtual +void LLPanelPeople::onChange(EStatusType status, const std::string &channelURI, bool proximal) +{ + if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL) + { + return; + } + + updateButtons(); +} + void LLPanelPeople::updateFriendList() { if (!mOnlineFriendList || !mAllFriendList) @@ -775,41 +791,20 @@ void LLPanelPeople::updateButtons() } } + bool enable_calls = gVoiceClient->voiceWorking() && gVoiceClient->voiceEnabled(); + buttonSetEnabled("teleport_btn", friends_tab_active && item_selected && isFriendOnline(selected_uuids.front())); buttonSetEnabled("view_profile_btn", item_selected); buttonSetEnabled("im_btn", multiple_selected); // allow starting the friends conference for multiple selection - buttonSetEnabled("call_btn", multiple_selected && canCall()); + buttonSetEnabled("call_btn", multiple_selected && enable_calls); buttonSetEnabled("share_btn", item_selected); // not implemented yet bool none_group_selected = item_selected && selected_id.isNull(); buttonSetEnabled("group_info_btn", !none_group_selected); - buttonSetEnabled("group_call_btn", !none_group_selected); + buttonSetEnabled("group_call_btn", !none_group_selected && enable_calls); buttonSetEnabled("chat_btn", !none_group_selected); } -bool LLPanelPeople::canCall() -{ - std::vector<LLUUID> selected_uuids; - getCurrentItemIDs(selected_uuids); - - bool result = false; - - std::vector<LLUUID>::const_iterator - id = selected_uuids.begin(), - uuids_end = selected_uuids.end(); - - for (;id != uuids_end; ++id) - { - if (LLAvatarActions::canCall(*id)) - { - result = true; - break; - } - } - - return result; -} - std::string LLPanelPeople::getActiveTabName() const { return mTabContainer->getCurrentPanel()->getName(); diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index 7580fdbeef..6d3d436156 100644 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -36,13 +36,16 @@ #include <llpanel.h> #include "llcallingcard.h" // for avatar tracker +#include "llvoiceclient.h" class LLFilterEditor; class LLTabContainer; class LLAvatarList; class LLGroupList; -class LLPanelPeople : public LLPanel +class LLPanelPeople + : public LLPanel + , public LLVoiceClientStatusObserver { LOG_CLASS(LLPanelPeople); public: @@ -52,6 +55,9 @@ public: /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); /*virtual*/ bool notifyChildren(const LLSD& info); + // Implements LLVoiceClientStatusObserver::onChange() to enable call buttons + // when voice is available + /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal); // internals class Updater; @@ -73,7 +79,6 @@ private: bool isFriendOnline(const LLUUID& id); bool isItemsFreeOfFriends(const std::vector<LLUUID>& uuids); - bool canCall(); void updateButtons(); std::string getActiveTabName() const; diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp index c1c10e6022..d9651a6045 100644 --- a/indra/newview/llpanelpeoplemenus.cpp +++ b/indra/newview/llpanelpeoplemenus.cpp @@ -183,20 +183,7 @@ bool NearbyMenu::enableContextMenuItem(const LLSD& userdata) } else if (item == std::string("can_call")) { - bool result = false; - std::vector<LLUUID>::const_iterator - id = mUUIDs.begin(), - uuids_end = mUUIDs.end(); - - for (;id != uuids_end; ++id) - { - if (LLAvatarActions::canCall(*id)) - { - result = true; - break; - } - } - return result; + return LLAvatarActions::canCall(); } return false; } diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index a4f0e55a93..a8a9717750 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -384,6 +384,10 @@ void LLPanelPlaces::onOpen(const LLSD& key) // Otherwise stop using land selection and deselect land. if (mPlaceInfoType == AGENT_INFO_TYPE) { + // We don't know if we are already added to LLViewerParcelMgr observers list + // so try to remove observer not to add an extra one. + parcel_mgr->removeObserver(mParcelObserver); + parcel_mgr->addObserver(mParcelObserver); parcel_mgr->selectParcelAt(gAgent.getPositionGlobal()); } @@ -898,6 +902,8 @@ void LLPanelPlaces::changedParcelSelection() if (!region || !parcel) return; + LLVector3d prev_pos_global = mPosGlobal; + // If agent is inside the selected parcel show agent's region<X, Y, Z>, // otherwise show region<X, Y, Z> of agent's selection point. bool is_current_parcel = is_agent_in_selected_parcel(parcel); @@ -914,7 +920,13 @@ void LLPanelPlaces::changedParcelSelection() } } - mPlaceProfile->resetLocation(); + // Reset location info only if global position is changed + // to reduce unnecessary text and icons updates. + if (prev_pos_global != mPosGlobal) + { + mPlaceProfile->resetLocation(); + } + mPlaceProfile->displaySelectedParcelInfo(parcel, region, mPosGlobal, is_current_parcel); updateVerbs(); diff --git a/indra/newview/llpanelprofileview.cpp b/indra/newview/llpanelprofileview.cpp index 7832f63e6a..044036ea50 100644 --- a/indra/newview/llpanelprofileview.cpp +++ b/indra/newview/llpanelprofileview.cpp @@ -101,8 +101,6 @@ void LLPanelProfileView::onOpen(const LLSD& key) id = key["id"]; } - // subscribe observer to get online status. Request will be sent by LLPanelAvatarProfile itself - mAvatarStatusObserver->subscribe(); if(id.notNull() && getAvatarId() != id) { setAvatarId(id); @@ -111,12 +109,9 @@ void LLPanelProfileView::onOpen(const LLSD& key) // Update the avatar name. gCacheName->get(getAvatarId(), FALSE, boost::bind(&LLPanelProfileView::onAvatarNameCached, this, _1, _2, _3, _4)); -/* -// disable this part of code according to EXT-2022. See processOnlineStatus - // status should only show if viewer has permission to view online/offline. EXT-453 - mStatusText->setVisible(isGrantedToSeeOnlineStatus()); + updateOnlineStatus(); -*/ + LLPanelProfile::onOpen(key); } @@ -164,27 +159,43 @@ bool LLPanelProfileView::isGrantedToSeeOnlineStatus() // *NOTE: GRANT_ONLINE_STATUS is always set to false while changing any other status. // When avatar disallow me to see her online status processOfflineNotification Message is received by the viewer // see comments for ChangeUserRights template message. EXT-453. -// return relationship->isRightGrantedFrom(LLRelationship::GRANT_ONLINE_STATUS); - return true; + // If GRANT_ONLINE_STATUS flag is changed it will be applied when viewer restarts. EXT-3880 + return relationship->isRightGrantedFrom(LLRelationship::GRANT_ONLINE_STATUS); } +// method was disabled according to EXT-2022. Re-enabled & improved according to EXT-3880 void LLPanelProfileView::updateOnlineStatus() { + // set text box visible to show online status for non-friends who has not set in Preferences + // "Only Friends & Groups can see when I am online" + mStatusText->setVisible(TRUE); + const LLRelationship* relationship = LLAvatarTracker::instance().getBuddyInfo(getAvatarId()); if (NULL == relationship) - return; + { + // this is non-friend avatar. Status will be updated from LLAvatarPropertiesProcessor. + // in LLPanelProfileView::processOnlineStatus() - bool online = relationship->isOnline(); + // subscribe observer to get online status. Request will be sent by LLPanelAvatarProfile itself. + // do not subscribe for friend avatar because online status can be wrong overridden + // via LLAvatarData::flags if Preferences: "Only Friends & Groups can see when I am online" is set. + mAvatarStatusObserver->subscribe(); + return; + } + // For friend let check if he allowed me to see his status - std::string status = getString(online ? "status_online" : "status_offline"); + // status should only show if viewer has permission to view online/offline. EXT-453, EXT-3880 + mStatusText->setVisible(isGrantedToSeeOnlineStatus()); - mStatusText->setValue(status); + bool online = relationship->isOnline(); + processOnlineStatus(online); } void LLPanelProfileView::processOnlineStatus(bool online) { - mAvatarIsOnline = online; - mStatusText->setVisible(online); + std::string status = getString(online ? "status_online" : "status_offline"); + + mStatusText->setValue(status); } void LLPanelProfileView::onAvatarNameCached(const LLUUID& id, const std::string& first_name, const std::string& last_name, BOOL is_group) @@ -193,17 +204,4 @@ void LLPanelProfileView::onAvatarNameCached(const LLUUID& id, const std::string& getChild<LLUICtrl>("user_name", FALSE)->setValue(first_name + " " + last_name); } -void LLPanelProfileView::togglePanel(LLPanel* panel, const LLSD& key) -{ - // *TODO: unused method? - - LLPanelProfile::togglePanel(panel); - if(FALSE == panel->getVisible()) - { - // LLPanelProfile::togglePanel shows/hides all children, - // we don't want to display online status for non friends, so re-hide it here - mStatusText->setVisible(mAvatarIsOnline); - } -} - // EOF diff --git a/indra/newview/llpanelprofileview.h b/indra/newview/llpanelprofileview.h index 5dc617d4a0..9b87e146a8 100644 --- a/indra/newview/llpanelprofileview.h +++ b/indra/newview/llpanelprofileview.h @@ -64,8 +64,6 @@ public: /*virtual*/ BOOL postBuild(); - /*virtual*/ void togglePanel(LLPanel* panel, const LLSD& key = LLSD()); - BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, @@ -81,8 +79,21 @@ public: protected: void onBackBtnClick(); - bool isGrantedToSeeOnlineStatus(); // deprecated after EXT-2022 is implemented - void updateOnlineStatus(); // deprecated after EXT-2022 is implemented + bool isGrantedToSeeOnlineStatus(); + + /** + * Displays avatar's online status if possible. + * + * Requirements from EXT-3880: + * For friends: + * - Online when online and privacy settings allow to show + * - Offline when offline and privacy settings allow to show + * - Else: nothing + * For other avatars: + * - Online when online and was not set in Preferences/"Only Friends & Groups can see when I am online" + * - Else: Offline + */ + void updateOnlineStatus(); void processOnlineStatus(bool online); private: @@ -96,7 +107,6 @@ private: LLTextBox* mStatusText; AvatarStatusObserver* mAvatarStatusObserver; - bool mAvatarIsOnline; }; #endif //LL_LLPANELPROFILEVIEW_H diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 88b706fb6b..c0302eee9e 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -628,7 +628,7 @@ bool LLParticipantList::LLParticipantListMenu::enableContextMenuItem(const LLSD& } else if (item == "can_call") { - return LLVoiceClient::voiceEnabled(); + return LLVoiceClient::voiceEnabled()&&gVoiceClient->voiceWorking(); } return true; diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 9608cd1263..6f9a1ccdbe 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -70,8 +70,6 @@ LLSpeaker::LLSpeaker(const LLUUID& id, const std::string& name, const ESpeakerTy { mDisplayName = name; } - - gVoiceClient->setUserVolume(id, LLMuteList::getInstance()->getSavedResidentVolume(id)); } diff --git a/indra/newview/lltransientdockablefloater.cpp b/indra/newview/lltransientdockablefloater.cpp index c9bfe178ce..9d39aa5182 100644 --- a/indra/newview/lltransientdockablefloater.cpp +++ b/indra/newview/lltransientdockablefloater.cpp @@ -48,6 +48,14 @@ LLTransientDockableFloater::LLTransientDockableFloater(LLDockControl* dockContro LLTransientDockableFloater::~LLTransientDockableFloater() { LLTransientFloaterMgr::getInstance()->unregisterTransientFloater(this); + LLView* dock = getDockWidget(); + LLTransientFloaterMgr::getInstance()->removeControlView( + LLTransientFloaterMgr::DOCKED, this); + if (dock != NULL) + { + LLTransientFloaterMgr::getInstance()->removeControlView( + LLTransientFloaterMgr::DOCKED, dock); + } } void LLTransientDockableFloater::setVisible(BOOL visible) @@ -55,18 +63,18 @@ void LLTransientDockableFloater::setVisible(BOOL visible) LLView* dock = getDockWidget(); if(visible && isDocked()) { - LLTransientFloaterMgr::getInstance()->addControlView(this); + LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::DOCKED, this); if (dock != NULL) { - LLTransientFloaterMgr::getInstance()->addControlView(dock); + LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::DOCKED, dock); } } else { - LLTransientFloaterMgr::getInstance()->removeControlView(this); + LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::DOCKED, this); if (dock != NULL) { - LLTransientFloaterMgr::getInstance()->removeControlView(dock); + LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::DOCKED, dock); } } @@ -78,18 +86,18 @@ void LLTransientDockableFloater::setDocked(bool docked, bool pop_on_undock) LLView* dock = getDockWidget(); if(docked) { - LLTransientFloaterMgr::getInstance()->addControlView(this); + LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::DOCKED, this); if (dock != NULL) { - LLTransientFloaterMgr::getInstance()->addControlView(dock); + LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::DOCKED, dock); } } else { - LLTransientFloaterMgr::getInstance()->removeControlView(this); + LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::DOCKED, this); if (dock != NULL) { - LLTransientFloaterMgr::getInstance()->removeControlView(dock); + LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::DOCKED, dock); } } diff --git a/indra/newview/lltransientfloatermgr.cpp b/indra/newview/lltransientfloatermgr.cpp index 8f1a738453..d82403070b 100644 --- a/indra/newview/lltransientfloatermgr.cpp +++ b/indra/newview/lltransientfloatermgr.cpp @@ -46,6 +46,7 @@ LLTransientFloaterMgr::LLTransientFloaterMgr() &LLTransientFloaterMgr::leftMouseClickCallback, this, _1, _2, _3)); mGroupControls.insert(std::pair<ETransientGroup, std::set<LLView*> >(GLOBAL, std::set<LLView*>())); + mGroupControls.insert(std::pair<ETransientGroup, std::set<LLView*> >(DOCKED, std::set<LLView*>())); mGroupControls.insert(std::pair<ETransientGroup, std::set<LLView*> >(IM, std::set<LLView*>())); } @@ -132,7 +133,8 @@ void LLTransientFloaterMgr::leftMouseClickCallback(S32 x, S32 y, return; } - bool hide = isControlClicked(mGroupControls.find(GLOBAL)->second, x, y); + bool hide = isControlClicked(mGroupControls.find(DOCKED)->second, x, y) + && isControlClicked(mGroupControls.find(GLOBAL)->second, x, y); if (hide) { hideTransientFloaters(x, y); diff --git a/indra/newview/lltransientfloatermgr.h b/indra/newview/lltransientfloatermgr.h index 1f99325a7f..9c5ae295f2 100644 --- a/indra/newview/lltransientfloatermgr.h +++ b/indra/newview/lltransientfloatermgr.h @@ -51,7 +51,7 @@ protected: public: enum ETransientGroup { - GLOBAL, IM + GLOBAL, DOCKED, IM }; void registerTransientFloater(LLTransientFloater* floater); diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index c84afa5af1..8ca0fd6ef6 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -37,8 +37,10 @@ // library includes #include "llnotificationsutil.h" +#include "llsdserialize.h" #include "llsdutil.h" + // project includes #include "llvoavatar.h" #include "llbufferstream.h" @@ -1092,6 +1094,119 @@ static void killGateway() #endif +class LLSpeakerVolumeStorage : public LLSingleton<LLSpeakerVolumeStorage> +{ + LOG_CLASS(LLSpeakerVolumeStorage); +public: + + /** + * Sets internal voluem level for specified user. + * + * @param[in] speaker_id - LLUUID of user to store volume level for + * @param[in] volume - internal volume level to be stored for user. + */ + void storeSpeakerVolume(const LLUUID& speaker_id, S32 volume); + + /** + * Gets stored internal volume level for specified speaker. + * + * If specified user is not found default level will be returned. It is equivalent of + * external level 0.5 from the 0.0..1.0 range. + * Default internal level is calculated as: internal = 400 * external^2 + * Maps 0.0 to 1.0 to internal values 0-400 with default 0.5 == 100 + * + * @param[in] speaker_id - LLUUID of user to get his volume level + */ + S32 getSpeakerVolume(const LLUUID& speaker_id); + +private: + friend class LLSingleton<LLSpeakerVolumeStorage>; + LLSpeakerVolumeStorage(); + ~LLSpeakerVolumeStorage(); + + const static std::string SETTINGS_FILE_NAME; + + void load(); + void save(); + + typedef std::map<LLUUID, S32> speaker_data_map_t; + speaker_data_map_t mSpeakersData; +}; + +const std::string LLSpeakerVolumeStorage::SETTINGS_FILE_NAME = "volume_settings.xml"; + +LLSpeakerVolumeStorage::LLSpeakerVolumeStorage() +{ + load(); +} + +LLSpeakerVolumeStorage::~LLSpeakerVolumeStorage() +{ + save(); +} + +void LLSpeakerVolumeStorage::storeSpeakerVolume(const LLUUID& speaker_id, S32 volume) +{ + mSpeakersData[speaker_id] = volume; +} + +S32 LLSpeakerVolumeStorage::getSpeakerVolume(const LLUUID& speaker_id) +{ + // default internal level of user voice. + const static LLUICachedControl<S32> DEFAULT_INTERNAL_VOLUME_LEVEL("VoiceDefaultInternalLevel", 100); + S32 ret_val = DEFAULT_INTERNAL_VOLUME_LEVEL; + speaker_data_map_t::const_iterator it = mSpeakersData.find(speaker_id); + + if (it != mSpeakersData.end()) + { + ret_val = it->second; + } + return ret_val; +} + +void LLSpeakerVolumeStorage::load() +{ + // load per-resident voice volume information + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SETTINGS_FILE_NAME); + + LLSD settings_llsd; + llifstream file; + file.open(filename); + if (file.is_open()) + { + LLSDSerialize::fromXML(settings_llsd, file); + } + + for (LLSD::map_const_iterator iter = settings_llsd.beginMap(); + iter != settings_llsd.endMap(); ++iter) + { + mSpeakersData.insert(std::make_pair(LLUUID(iter->first), (S32)iter->second.asInteger())); + } +} + +void LLSpeakerVolumeStorage::save() +{ + // If we quit from the login screen we will not have an SL account + // name. Don't try to save, otherwise we'll dump a file in + // C:\Program Files\SecondLife\ or similar. JC + std::string user_dir = gDirUtilp->getLindenUserDir(); + if (!user_dir.empty()) + { + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SETTINGS_FILE_NAME); + LLSD settings_llsd; + + for(speaker_data_map_t::const_iterator iter = mSpeakersData.begin(); iter != mSpeakersData.end(); ++iter) + { + settings_llsd[iter->first.asString()] = iter->second; + } + + llofstream file; + file.open(filename); + LLSDSerialize::toPrettyXML(settings_llsd, file); + } +} + + /////////////////////////////////////////////////////////////////////////////////////////////// LLVoiceClient::LLVoiceClient() : @@ -4914,7 +5029,9 @@ LLVoiceClient::participantState *LLVoiceClient::sessionState::addParticipant(con } mParticipantsByUUID.insert(participantUUIDMap::value_type(&(result->mAvatarID), result)); - + + result->mUserVolume = LLSpeakerVolumeStorage::getInstance()->getSpeakerVolume(result->mAvatarID); + LL_DEBUGS("Voice") << "participant \"" << result->mURI << "\" added." << LL_ENDL; } @@ -5853,6 +5970,11 @@ bool LLVoiceClient::voiceEnabled() return gSavedSettings.getBOOL("EnableVoiceChat") && !gSavedSettings.getBOOL("CmdLineDisableVoice"); } +bool LLVoiceClient::voiceWorking() +{ + return (stateLoggedIn <= mState) && (mState <= stateLeavingSession); +} + void LLVoiceClient::setLipSyncEnabled(BOOL enabled) { mLipSyncEnabled = enabled; @@ -6158,6 +6280,9 @@ void LLVoiceClient::setUserVolume(const LLUUID& id, F32 volume) participant->mUserVolume = llclamp(ivol, 0, 400); participant->mVolumeDirty = TRUE; mAudioSession->mVolumeDirty = TRUE; + + // store this volume setting for future sessions + LLSpeakerVolumeStorage::getInstance()->storeSpeakerVolume(id, participant->mUserVolume); } } } diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index 6231c6ba29..8f668dff19 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -191,6 +191,8 @@ static void updatePosition(void); void inputUserControlState(bool down); // interpret any sort of up-down mic-open control input according to ptt-toggle prefs void setVoiceEnabled(bool enabled); static bool voiceEnabled(); + // Checks is voice working judging from mState + bool voiceWorking(); void setUsePTT(bool usePTT); void setPTTIsToggle(bool PTTIsToggle); bool getPTTIsToggle(); diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 613530b7aa..d2e5473157 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -11,7 +11,7 @@ can_dock="false" can_minimize="true" can_close="true" - visible="true" + visible="false" width="360" can_resize="true" min_width="250" diff --git a/indra/newview/skins/default/xui/en/floater_voice_controls.xml b/indra/newview/skins/default/xui/en/floater_voice_controls.xml index f473a51ff6..c4411db8c5 100644 --- a/indra/newview/skins/default/xui/en/floater_voice_controls.xml +++ b/indra/newview/skins/default/xui/en/floater_voice_controls.xml @@ -56,7 +56,7 @@ height="18" default_icon_name="Generic_Person" layout="topleft" - left="0" + left="5" name="user_icon" top="0" width="18" /> @@ -78,6 +78,7 @@ follows="top|right" height="16" layout="topleft" + right="-3" name="speaking_indicator" left_pad="5" visible="true" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 960da7a274..41f4621d66 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -244,6 +244,16 @@ Save all changes to clothing/body parts? <notification icon="alertmodal.tga" + name="FriendsAndGroupsOnly" + type="alertmodal"> + Non-friends won't know that you've choosen to ignore their calls and instant messages. + <usetemplate + name="okbutton" + yestext="Yes"/> + </notification> + + <notification + icon="alertmodal.tga" name="GrantModifyRights" type="alertmodal"> Granting modify rights to another Resident allows them to change, delete or take ANY objects you may have in-world. Be VERY careful when handing out this permission. 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 615ade99a2..c605975c8e 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 @@ -65,28 +65,18 @@ height="15" layout="topleft" left_pad="5" + right="-72" name="last_interaction" text_color="LtGray_50" value="0s" width="24" /> - <output_monitor - auto_update="true" - follows="right" - draw_border="false" - height="16" - layout="topleft" - left_pad="5" - mouse_opaque="true" - name="speaking_indicator" - visible="true" - width="20" /> <button follows="right" height="16" image_pressed="Info_Press" image_unselected="Info_Over" left_pad="3" - right="-31" + right="-53" name="info_btn" top_delta="-2" width="16" /> @@ -96,9 +86,21 @@ image_overlay="ForwardArrow_Off" layout="topleft" left_pad="5" - right="-3" + right="-28" name="profile_btn" tool_tip="View profile" top_delta="-2" width="20" /> + <output_monitor + auto_update="true" + follows="right" + draw_border="false" + height="16" + layout="topleft" + left_pad="5" + right="-3" + mouse_opaque="true" + name="speaking_indicator" + visible="true" + width="20" /> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_group_land_money.xml b/indra/newview/skins/default/xui/en/panel_group_land_money.xml index 2075d7e05b..db156f7877 100644 --- a/indra/newview/skins/default/xui/en/panel_group_land_money.xml +++ b/indra/newview/skins/default/xui/en/panel_group_land_money.xml @@ -2,7 +2,7 @@ <panel border="false" follows="all" - height="380" + height="420" label="Land & L$" layout="topleft" left="0" @@ -237,7 +237,7 @@ </text> <tab_container follows="all" - height="173" + height="180" halign="center" layout="topleft" left="0" @@ -250,7 +250,7 @@ <panel border="false" follows="all" - height="173" + height="180" label="PLANNING" layout="topleft" left="0" @@ -275,7 +275,7 @@ <panel border="false" follows="all" - height="173" + height="180" label="DETAILS" layout="topleft" left="0" @@ -296,41 +296,44 @@ word_wrap="true"> Loading... </text_editor> + + <button + height="20" + image_overlay="Arrow_Left_Off" + layout="topleft" + left="5" + name="earlier_details_button" + tool_tip="Go back in time" + top_pad="10" + width="25" /> <button - follows="left|top" - height="18" - image_overlay="Arrow_Left_Off" - layout="topleft" - name="earlier_details_button" - tool_tip="Back" - right="-45" - bottom="0" - width="25" /> - <button - follows="left|top" - height="18" - image_overlay="Arrow_Right_Off" - layout="topleft" - left_pad="10" - name="later_details_button" - tool_tip="Next" - width="25" /> - </panel> + height="20" + image_overlay="Arrow_Right_Off" + layout="topleft" + left_pad="5" + name="later_details_button" + tool_tip="Go forward in time" + top_delta="0" + width="25" /> + + + </panel> <panel border="false" follows="all" - height="173" + height="180" label="SALES" layout="topleft" left_delta="0" help_topic="group_money_sales_tab" + mouse_opaque="false" name="group_money_sales_tab" top="0" width="300"> <text_editor type="string" follows="all" - height="140" + height="130" layout="topleft" left="0" max_length="4096" @@ -340,25 +343,24 @@ word_wrap="true"> Loading... </text_editor> - <button - bottom="0" - follows="left|top" - height="18" - image_overlay="Arrow_Left_Off" - layout="topleft" - name="earlier_sales_button" - tool_tip="Back" - right="-45" - width="25" /> - <button - follows="left|top" - height="18" - image_overlay="Arrow_Right_Off" - layout="topleft" - left_pad="10" - name="later_sales_button" - tool_tip="Next" - width="25" /> + <button + height="20" + image_overlay="Arrow_Left_Off" + layout="topleft" + left="5" + name="earlier_sales_button" + tool_tip="Go back in time" + top_pad="10" + width="25" /> + <button + height="20" + image_overlay="Arrow_Right_Off" + layout="topleft" + left_pad="5" + name="later_sales_button" + tool_tip="Go forward in time" + top_delta="0" + width="25" /> </panel> </tab_container> </panel> |