Add bulk speaker updates. Sped up speaker fetching by disabling list sorting during bulk updates.

This commit is contained in:
Shyotl
2018-02-07 21:18:35 -06:00
parent fa628ce4d1
commit 30df7dacde
6 changed files with 177 additions and 74 deletions

View File

@@ -125,6 +125,7 @@ LLScrollListCtrl::LLScrollListCtrl(const std::string& name, const LLRect& rect,
mNeedsScroll(false), mNeedsScroll(false),
mCanSelect(true), mCanSelect(true),
mColumnsDirty(false), mColumnsDirty(false),
mSortEnabled(true),
mMaxItemCount(INT_MAX), mMaxItemCount(INT_MAX),
mMaxContentWidth(0), mMaxContentWidth(0),
mBorderThickness( 2 ), mBorderThickness( 2 ),
@@ -2301,6 +2302,16 @@ BOOL LLScrollListCtrl::setSort(S32 column_idx, BOOL ascending)
} }
} }
void LLScrollListCtrl::setSortEnabled(bool sort)
{
bool update = sort && !mSortEnabled;
mSortEnabled = sort;
if (update)
{
updateSort();
}
}
S32 LLScrollListCtrl::getLinesPerPage() S32 LLScrollListCtrl::getLinesPerPage()
{ {
//if mPageLines is NOT provided display all item //if mPageLines is NOT provided display all item
@@ -2942,7 +2953,7 @@ std::string LLScrollListCtrl::getSortColumnName()
BOOL LLScrollListCtrl::hasSortOrder() const BOOL LLScrollListCtrl::hasSortOrder() const
{ {
return !mSortColumns.empty(); return mSortEnabled && !mSortColumns.empty();
} }
void LLScrollListCtrl::clearSortOrder() void LLScrollListCtrl::clearSortOrder()

View File

@@ -322,6 +322,7 @@ public:
BOOL getSortAscending() { return mSortColumns.empty() ? TRUE : mSortColumns.back().second; } BOOL getSortAscending() { return mSortColumns.empty() ? TRUE : mSortColumns.back().second; }
BOOL hasSortOrder() const; BOOL hasSortOrder() const;
void clearSortOrder(); void clearSortOrder();
void setSortEnabled(bool sort);
template<typename T> S32 selectMultiple(const std::vector<T>& vec) template<typename T> S32 selectMultiple(const std::vector<T>& vec)
{ {
@@ -423,6 +424,7 @@ private:
bool mDisplayColumnHeaders; bool mDisplayColumnHeaders;
bool mColumnsDirty; bool mColumnsDirty;
bool mColumnWidthsDirty; bool mColumnWidthsDirty;
bool mSortEnabled;
mutable item_list mItemList; mutable item_list mItemList;

View File

@@ -58,10 +58,13 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source,
mSpeakerClearListener = new SpeakerClearListener(*this); mSpeakerClearListener = new SpeakerClearListener(*this);
//mSpeakerModeratorListener = new SpeakerModeratorUpdateListener(*this); //mSpeakerModeratorListener = new SpeakerModeratorUpdateListener(*this);
mSpeakerMuteListener = new SpeakerMuteListener(*this); mSpeakerMuteListener = new SpeakerMuteListener(*this);
mSpeakerBatchBeginListener = new SpeakerBatchBeginListener(*this);
mSpeakerBatchEndListener = new SpeakerBatchEndListener(*this);
mSpeakerMgr->addListener(mSpeakerAddListener, "add"); mSpeakerMgr->addListener(mSpeakerAddListener, "add");
mSpeakerMgr->addListener(mSpeakerRemoveListener, "remove"); mSpeakerMgr->addListener(mSpeakerRemoveListener, "remove");
mSpeakerMgr->addListener(mSpeakerClearListener, "clear"); mSpeakerMgr->addListener(mSpeakerClearListener, "clear");
mSpeakerMgr->addListener(mSpeakerBatchBeginListener, "batch_begin");
mSpeakerMgr->addListener(mSpeakerBatchEndListener, "batch_end");
//mSpeakerMgr->addListener(mSpeakerModeratorListener, "update_moderator"); //mSpeakerMgr->addListener(mSpeakerModeratorListener, "update_moderator");
} }
@@ -378,6 +381,16 @@ bool LLParticipantList::onSpeakerMuteEvent(LLPointer<LLOldEvents::LLEvent> event
return true; return true;
} }
void LLParticipantList::onSpeakerBatchBeginEvent()
{
mAvatarList->setSortEnabled(false);
}
void LLParticipantList::onSpeakerBatchEndEvent()
{
mAvatarList->setSortEnabled(true);
}
void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id) void LLParticipantList::addAvatarIDExceptAgent(const LLUUID& avatar_id)
{ {
//if (mExcludeAgent && gAgent.getID() == avatar_id) return; //if (mExcludeAgent && gAgent.getID() == avatar_id) return;
@@ -468,6 +481,17 @@ bool LLParticipantList::SpeakerMuteListener::handleEvent(LLPointer<LLOldEvents::
return mParent.onSpeakerMuteEvent(event, userdata); return mParent.onSpeakerMuteEvent(event, userdata);
} }
bool LLParticipantList::SpeakerBatchBeginListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
{
mParent.onSpeakerBatchBeginEvent();
return true;
}
bool LLParticipantList::SpeakerBatchEndListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
{
mParent.onSpeakerBatchEndEvent();
return true;
}
// Singu Note: The following functions are actually of the LLParticipantListMenu class, but we haven't married lists with menus yet. // Singu Note: The following functions are actually of the LLParticipantListMenu class, but we haven't married lists with menus yet.
void LLParticipantList::toggleAllowTextChat(const LLSD& userdata) void LLParticipantList::toggleAllowTextChat(const LLSD& userdata)
{ {

View File

@@ -76,6 +76,8 @@ protected:
bool onClearListEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); bool onClearListEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
//bool onModeratorUpdateEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); //bool onModeratorUpdateEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
bool onSpeakerMuteEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); bool onSpeakerMuteEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
void onSpeakerBatchBeginEvent();
void onSpeakerBatchEndEvent();
/** /**
* List of listeners implementing LLOldEvents::LLSimpleListener. * List of listeners implementing LLOldEvents::LLSimpleListener.
@@ -126,6 +128,20 @@ protected:
/*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
}; };
class SpeakerBatchBeginListener : public BaseSpeakerListener
{
public:
SpeakerBatchBeginListener(LLParticipantList& parent) : BaseSpeakerListener(parent) {}
/*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
};
class SpeakerBatchEndListener : public BaseSpeakerListener
{
public:
SpeakerBatchEndListener(LLParticipantList& parent) : BaseSpeakerListener(parent) {}
/*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
};
/** /**
* Menu used in the participant list. * Menu used in the participant list.
class LLParticipantListMenu : public LLListContextMenu class LLParticipantListMenu : public LLListContextMenu
@@ -202,6 +218,8 @@ private:
LLPointer<SpeakerClearListener> mSpeakerClearListener; LLPointer<SpeakerClearListener> mSpeakerClearListener;
//LLPointer<SpeakerModeratorUpdateListener> mSpeakerModeratorListener; //LLPointer<SpeakerModeratorUpdateListener> mSpeakerModeratorListener;
LLPointer<SpeakerMuteListener> mSpeakerMuteListener; LLPointer<SpeakerMuteListener> mSpeakerMuteListener;
LLPointer<SpeakerBatchBeginListener> mSpeakerBatchBeginListener;
LLPointer<SpeakerBatchEndListener> mSpeakerBatchEndListener;
validate_speaker_callback_t mValidateSpeakerCallback; validate_speaker_callback_t mValidateSpeakerCallback;
}; };

View File

@@ -338,7 +338,20 @@ LLSpeakerMgr::~LLSpeakerMgr()
delete mSpeakerDelayRemover; delete mSpeakerDelayRemover;
} }
LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::string& name, LLSpeaker::ESpeakerStatus status, LLSpeaker::ESpeakerType type) void LLSpeakerMgr::setSpeakers(const std::vector<LLSpeakerMgr::speaker_entry_t>& speakers)
{
if (!speakers.empty())
{
fireEvent(new LLOldEvents::LLEvent(this), "batch_begin");
for (auto entry : speakers)
{
setSpeaker(entry.id, entry.name, entry.status, entry.type, entry.moderator, entry.moderator_muted_text);
}
fireEvent(new LLOldEvents::LLEvent(this), "batch_end");
}
}
LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::string& name, LLSpeaker::ESpeakerStatus status, LLSpeaker::ESpeakerType type, bool moderator, bool moderator_muted_text)
{ {
LLUUID session_id = getSessionID(); LLUUID session_id = getSessionID();
if (id.isNull() || (id == session_id)) if (id.isNull() || (id == session_id))
@@ -347,34 +360,37 @@ LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::strin
} }
LLPointer<LLSpeaker> speakerp; LLPointer<LLSpeaker> speakerp;
if (mSpeakers.find(id) == mSpeakers.end()) auto it = mSpeakers.find(id);
if (it == mSpeakers.end() || it->second.isNull())
{ {
speakerp = new LLSpeaker(id, name, type); speakerp = new LLSpeaker(id, name, type);
speakerp->mStatus = status; speakerp->mStatus = status;
speakerp->mIsModerator = moderator;
speakerp->mModeratorMutedText = moderator_muted_text;
mSpeakers.insert(std::make_pair(speakerp->mID, speakerp)); mSpeakers.insert(std::make_pair(speakerp->mID, speakerp));
mSpeakersSorted.push_back(speakerp); mSpeakersSorted.push_back(speakerp);
LL_DEBUGS("Speakers") << "Added speaker " << id << LL_ENDL;
fireEvent(new LLSpeakerListChangeEvent(this, speakerp->mID), "add"); fireEvent(new LLSpeakerListChangeEvent(this, speakerp->mID), "add");
} }
else else
{ {
speakerp = findSpeaker(id); speakerp = it->second;
if (speakerp.notNull()) bool update_moderator = (bool)speakerp->mIsModerator != moderator;
// keep highest priority status (lowest value) instead of overriding current value
speakerp->mStatus = llmin(speakerp->mStatus, status);
speakerp->mIsModerator = moderator;
speakerp->mModeratorMutedText = moderator_muted_text;
// RN: due to a weird behavior where IMs from attached objects come from the wearer's agent_id
// we need to override speakers that we think are objects when we find out they are really
// residents
if (type == LLSpeaker::SPEAKER_AGENT)
{ {
// keep highest priority status (lowest value) instead of overriding current value speakerp->mType = LLSpeaker::SPEAKER_AGENT;
speakerp->mStatus = llmin(speakerp->mStatus, status); speakerp->lookupName();
// RN: due to a weird behavior where IMs from attached objects come from the wearer's agent_id
// we need to override speakers that we think are objects when we find out they are really
// residents
if (type == LLSpeaker::SPEAKER_AGENT)
{
speakerp->mType = LLSpeaker::SPEAKER_AGENT;
speakerp->lookupName();
}
} }
else if (update_moderator)
{ {
LL_WARNS("Speakers") << "Speaker " << id << " not found" << LL_ENDL; fireEvent(new LLSpeakerUpdateModeratorEvent(speakerp), "update_moderator");
} }
} }
@@ -534,13 +550,17 @@ void LLSpeakerMgr::updateSpeakerList()
std::set<LLUUID> participants; std::set<LLUUID> participants;
LLVoiceClient::getInstance()->getParticipantList(participants); LLVoiceClient::getInstance()->getParticipantList(participants);
// If we are, add all voice client participants to our list of known speakers // If we are, add all voice client participants to our list of known speakers
std::vector<speaker_entry_t> speakers;
speakers.reserve(participants.size());
for (std::set<LLUUID>::iterator participant_it = participants.begin(); participant_it != participants.end(); ++participant_it) for (std::set<LLUUID>::iterator participant_it = participants.begin(); participant_it != participants.end(); ++participant_it)
{ {
setSpeaker(*participant_it, speakers.emplace_back(speaker_entry_t(
LLVoiceClient::getInstance()->getDisplayName(*participant_it), *participant_it,
LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::STATUS_VOICE_ACTIVE,
(LLVoiceClient::getInstance()->isParticipantAvatar(*participant_it)?LLSpeaker::SPEAKER_AGENT:LLSpeaker::SPEAKER_EXTERNAL)); LLVoiceClient::getInstance()->getDisplayName(*participant_it),
(LLVoiceClient::getInstance()->isParticipantAvatar(*participant_it)?LLSpeaker::SPEAKER_AGENT:LLSpeaker::SPEAKER_EXTERNAL)));
} }
setSpeakers(speakers);
} }
else else
{ {
@@ -569,10 +589,11 @@ void LLSpeakerMgr::updateSpeakerList()
} }
else if (gdatap && gdatap->isMemberDataComplete() && !gdatap->mMembers.empty()) else if (gdatap && gdatap->isMemberDataComplete() && !gdatap->mMembers.empty())
{ {
std::vector<speaker_entry_t> speakers;
speakers.reserve(gdatap->mMembers.size());
// Add group members when we get the complete list (note: can take a while before we get that list) // Add group members when we get the complete list (note: can take a while before we get that list)
LLGroupMgrGroupData::member_list_t::iterator member_it = gdatap->mMembers.begin(); LLGroupMgrGroupData::member_list_t::iterator member_it = gdatap->mMembers.begin();
const S32 load_group_max_members = gSavedSettings.getS32("ChatLoadGroupMaxMembers");
S32 updated = 0;
while (member_it != gdatap->mMembers.end()) while (member_it != gdatap->mMembers.end())
{ {
LLGroupMemberData* member = member_it->second; LLGroupMemberData* member = member_it->second;
@@ -581,16 +602,16 @@ void LLSpeakerMgr::updateSpeakerList()
const std::string& localized_online(); const std::string& localized_online();
if ((member->getOnlineStatus() == localized_online()) && (mSpeakers.find(id) == mSpeakers.end())) if ((member->getOnlineStatus() == localized_online()) && (mSpeakers.find(id) == mSpeakers.end()))
{ {
LLPointer<LLSpeaker> speakerp = setSpeaker(id, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); speakers.emplace_back(speaker_entry_t(
speakerp->mIsModerator = ((member->getAgentPowers() & GP_SESSION_MODERATOR) == GP_SESSION_MODERATOR); id,
updated++; LLSpeaker::STATUS_VOICE_ACTIVE,
"",
LLSpeaker::SPEAKER_AGENT,
(member->getAgentPowers() & GP_SESSION_MODERATOR) == GP_SESSION_MODERATOR));
} }
++member_it; ++member_it;
// Limit the number of "manually updated" participants to a reasonable number to avoid severe fps drop
// *TODO : solve the perf issue of having several hundreds of widgets in the conversation list
if (updated >= load_group_max_members)
break;
} }
setSpeakers(speakers);
mSpeakerListUpdated = true; mSpeakerListUpdated = true;
} }
} }
@@ -617,7 +638,7 @@ void LLSpeakerMgr::updateSpeakerList()
} }
} }
// Always add the current agent (it has to be there...). Will do nothing if already there. // Always add the current agent (it has to be there...). Will do nothing if already there.
setSpeaker(gAgentID, "", LLSpeaker::STATUS_VOICE_ACTIVE, LLSpeaker::SPEAKER_AGENT); setSpeaker(gAgentID, "", LLSpeaker::STATUS_VOICE_ACTIVE);
} }
void LLSpeakerMgr::setSpeakerNotInChannel(LLSpeaker* speakerp) void LLSpeakerMgr::setSpeakerNotInChannel(LLSpeaker* speakerp)
@@ -737,6 +758,7 @@ void LLIMSpeakerMgr::setSpeakers(const LLSD& speakers)
{ {
if ( !speakers.isMap() ) return; if ( !speakers.isMap() ) return;
std::vector<speaker_entry_t> speakerentries;
if ( speakers.has("agent_info") && speakers["agent_info"].isMap() ) if ( speakers.has("agent_info") && speakers["agent_info"].isMap() )
{ {
LLSD::map_const_iterator speaker_it; LLSD::map_const_iterator speaker_it;
@@ -744,26 +766,21 @@ void LLIMSpeakerMgr::setSpeakers(const LLSD& speakers)
speaker_it != speakers["agent_info"].endMap(); speaker_it != speakers["agent_info"].endMap();
++speaker_it) ++speaker_it)
{ {
LLUUID agent_id(speaker_it->first); bool moderator = false;
bool moderator_muted = false;
LLPointer<LLSpeaker> speakerp = setSpeaker( if (speaker_it->second.isMap())
agent_id,
LLStringUtil::null,
LLSpeaker::STATUS_TEXT_ONLY);
if ( speaker_it->second.isMap() )
{ {
BOOL is_moderator = speakerp->mIsModerator; moderator = speaker_it->second["is_moderator"];
speakerp->mIsModerator = speaker_it->second["is_moderator"]; moderator_muted = speaker_it->second["mutes"]["text"];
speakerp->mModeratorMutedText =
speaker_it->second["mutes"]["text"];
// Fire event only if moderator changed
if ( is_moderator != speakerp->mIsModerator )
{
LL_DEBUGS("Speakers") << "Speaker " << agent_id << (is_moderator ? "is now" : "no longer is") << " a moderator" << LL_ENDL;
fireEvent(new LLSpeakerUpdateModeratorEvent(speakerp), "update_moderator");
}
} }
speakerentries.emplace_back(
LLUUID(speaker_it->first),
LLSpeaker::STATUS_TEXT_ONLY,
"",
LLSpeaker::SPEAKER_AGENT,
moderator,
moderator_muted
);
} }
} }
else if ( speakers.has("agents" ) && speakers["agents"].isArray() ) else if ( speakers.has("agents" ) && speakers["agents"].isArray() )
@@ -775,22 +792,20 @@ void LLIMSpeakerMgr::setSpeakers(const LLSD& speakers)
speaker_it != speakers["agents"].endArray(); speaker_it != speakers["agents"].endArray();
++speaker_it) ++speaker_it)
{ {
const LLUUID agent_id = (*speaker_it).asUUID(); speakerentries.emplace_back((*speaker_it).asUUID());
LLPointer<LLSpeaker> speakerp = setSpeaker(
agent_id,
LLStringUtil::null,
LLSpeaker::STATUS_TEXT_ONLY);
} }
} }
LLSpeakerMgr::setSpeakers(speakerentries);
} }
void LLIMSpeakerMgr::updateSpeakers(const LLSD& update) void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
{ {
if ( !update.isMap() ) return; if ( !update.isMap() ) return;
std::vector<speaker_entry_t> speakerentries;
if ( update.has("agent_updates") && update["agent_updates"].isMap() ) if ( update.has("agent_updates") && update["agent_updates"].isMap() )
{ {
LLSD::map_const_iterator update_it; LLSD::map_const_iterator update_it;
for( for(
update_it = update["agent_updates"].beginMap(); update_it = update["agent_updates"].beginMap();
@@ -800,8 +815,11 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
LLUUID agent_id(update_it->first); LLUUID agent_id(update_it->first);
LLPointer<LLSpeaker> speakerp = findSpeaker(agent_id); LLPointer<LLSpeaker> speakerp = findSpeaker(agent_id);
LLSD agent_data = update_it->second; bool new_speaker = false;
bool moderator = false;
bool moderator_muted = false;
LLSD agent_data = update_it->second;
if (agent_data.isMap() && agent_data.has("transition")) if (agent_data.isMap() && agent_data.has("transition"))
{ {
if (agent_data["transition"].asString() == "LEAVE" && speakerp.notNull()) if (agent_data["transition"].asString() == "LEAVE" && speakerp.notNull())
@@ -811,15 +829,17 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
else if (agent_data["transition"].asString() == "ENTER") else if (agent_data["transition"].asString() == "ENTER")
{ {
// add or update speaker // add or update speaker
speakerp = setSpeaker(agent_id); new_speaker = true;
} }
else else
{ {
LL_WARNS() << "bad membership list update from 'agent_updates' for agent " << agent_id << ", transition " << ll_print_sd(agent_data["transition"]) << LL_ENDL; LL_WARNS() << "bad membership list update from 'agent_updates' for agent " << agent_id << ", transition " << ll_print_sd(agent_data["transition"]) << LL_ENDL;
} }
} }
if (speakerp.isNull() && !new_speaker)
if (speakerp.isNull()) continue; {
continue;
}
// should have a valid speaker from this point on // should have a valid speaker from this point on
if (agent_data.isMap() && agent_data.has("info")) if (agent_data.isMap() && agent_data.has("info"))
@@ -828,21 +848,21 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
if (agent_info.has("is_moderator")) if (agent_info.has("is_moderator"))
{ {
BOOL is_moderator = speakerp->mIsModerator; moderator = agent_info["is_moderator"];
speakerp->mIsModerator = agent_info["is_moderator"];
// Fire event only if moderator changed
if ( is_moderator != speakerp->mIsModerator )
{
LL_DEBUGS("Speakers") << "Speaker " << agent_id << (is_moderator ? "is now" : "no longer is") << " a moderator" << LL_ENDL;
fireEvent(new LLSpeakerUpdateModeratorEvent(speakerp), "update_moderator");
}
} }
if (agent_info.has("mutes")) if (agent_info.has("mutes"))
{ {
speakerp->mModeratorMutedText = agent_info["mutes"]["text"]; moderator_muted = agent_info["mutes"]["text"];
} }
} }
speakerentries.emplace_back(
agent_id,
LLSpeaker::STATUS_TEXT_ONLY,
"",
LLSpeaker::SPEAKER_AGENT,
moderator,
moderator_muted
);
} }
} }
else if ( update.has("updates") && update["updates"].isMap() ) else if ( update.has("updates") && update["updates"].isMap() )
@@ -864,7 +884,9 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
else if ( agent_transition == "ENTER") else if ( agent_transition == "ENTER")
{ {
// add or update speaker // add or update speaker
speakerp = setSpeaker(agent_id); speakerentries.emplace_back(
agent_id
);
} }
else else
{ {
@@ -872,6 +894,7 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
} }
} }
} }
LLSpeakerMgr::setSpeakers(speakerentries);
} }
void LLIMSpeakerMgr::toggleAllowTextChat(const LLUUID& speaker_id) void LLIMSpeakerMgr::toggleAllowTextChat(const LLUUID& speaker_id)
@@ -1039,10 +1062,13 @@ void LLLocalSpeakerMgr::updateSpeakerList()
// pick up non-voice speakers in chat range // pick up non-voice speakers in chat range
uuid_vec_t avatar_ids; uuid_vec_t avatar_ids;
LLWorld::getInstance()->getAvatars(&avatar_ids, nullptr, gAgent.getPositionGlobal(), CHAT_NORMAL_RADIUS); LLWorld::getInstance()->getAvatars(&avatar_ids, nullptr, gAgent.getPositionGlobal(), CHAT_NORMAL_RADIUS);
std::vector<speaker_entry_t> speakers;
speakers.reserve(avatar_ids.size());
for (const auto& id : avatar_ids) for (const auto& id : avatar_ids)
{ {
setSpeaker(id); speakers.emplace_back(id);
} }
setSpeakers(speakers);
// check if text only speakers have moved out of chat range // check if text only speakers have moved out of chat range
for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); ++speaker_it) for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); ++speaker_it)

View File

@@ -230,10 +230,32 @@ public:
void update(BOOL resort_ok); void update(BOOL resort_ok);
void setSpeakerTyping(const LLUUID& speaker_id, BOOL typing); void setSpeakerTyping(const LLUUID& speaker_id, BOOL typing);
void speakerChatted(const LLUUID& speaker_id); void speakerChatted(const LLUUID& speaker_id);
struct speaker_entry_t
{
speaker_entry_t(const LLUUID& id,
LLSpeaker::ESpeakerStatus status = LLSpeaker::STATUS_TEXT_ONLY,
const std::string& name = LLStringUtil::null,
LLSpeaker::ESpeakerType type = LLSpeaker::SPEAKER_AGENT,
const bool moderator = false,
const bool moderator_muted_text = false) :
id(id), name(name), status(status), type(type), moderator(moderator), moderator_muted_text(moderator_muted_text)
{}
const LLUUID id;
const std::string name;
const LLSpeaker::ESpeakerStatus status;
const LLSpeaker::ESpeakerType type;
const bool moderator;
const bool moderator_muted_text;
};
void setSpeakers(const std::vector<speaker_entry_t>& speakers);
LLPointer<LLSpeaker> setSpeaker(const LLUUID& id, LLPointer<LLSpeaker> setSpeaker(const LLUUID& id,
const std::string& name = LLStringUtil::null, const std::string& name = LLStringUtil::null,
LLSpeaker::ESpeakerStatus status = LLSpeaker::STATUS_TEXT_ONLY, LLSpeaker::ESpeakerStatus status = LLSpeaker::STATUS_TEXT_ONLY,
LLSpeaker::ESpeakerType = LLSpeaker::SPEAKER_AGENT); LLSpeaker::ESpeakerType = LLSpeaker::SPEAKER_AGENT,
bool moderator = false,
bool moderator_muted_text = false);
BOOL isVoiceActive(); BOOL isVoiceActive();