Merge branch 'master' of git@github.com:Shyotl/SingularityViewer.git
This commit is contained in:
@@ -502,12 +502,14 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos, BOOL r
|
|||||||
|
|
||||||
case ADD_SORTED:
|
case ADD_SORTED:
|
||||||
{
|
{
|
||||||
// sort by column 0, in ascending order
|
|
||||||
std::vector<sort_column_t> single_sort_column;
|
|
||||||
single_sort_column.push_back(std::make_pair(0, TRUE));
|
|
||||||
|
|
||||||
mItemList.push_back(item);
|
mItemList.push_back(item);
|
||||||
std::stable_sort(mItemList.begin(), mItemList.end(), SortScrollListItem(single_sort_column,mSortCallback));
|
// std::stable_sort is expensive. Only do this if the user sort criteria is not column 0, otherwise
|
||||||
|
// setNeedsSort does what we want.
|
||||||
|
if (mSortColumns.empty() || mSortColumns[0].first != 0)
|
||||||
|
{
|
||||||
|
// sort by column 0, in ascending order
|
||||||
|
std::stable_sort(mItemList.begin(), mItemList.end(), SortScrollListItem({ {0,true} }, mSortCallback));
|
||||||
|
}
|
||||||
|
|
||||||
// ADD_SORTED just sorts by first column...
|
// ADD_SORTED just sorts by first column...
|
||||||
// this might not match user sort criteria, so flag list as being in unsorted state
|
// this might not match user sort criteria, so flag list as being in unsorted state
|
||||||
|
|||||||
@@ -369,6 +369,7 @@ public:
|
|||||||
return mSortCallback->connect(cb);
|
return mSortCallback->connect(cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
S32 getLinesPerPage();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// "Full" interface: use this when you're creating a list that has one or more of the following:
|
// "Full" interface: use this when you're creating a list that has one or more of the following:
|
||||||
@@ -405,7 +406,6 @@ private:
|
|||||||
void deselectItem(LLScrollListItem* itemp);
|
void deselectItem(LLScrollListItem* itemp);
|
||||||
void commitIfChanged();
|
void commitIfChanged();
|
||||||
BOOL setSort(S32 column, BOOL ascending);
|
BOOL setSort(S32 column, BOOL ascending);
|
||||||
S32 getLinesPerPage();
|
|
||||||
|
|
||||||
S32 mLineHeight; // the max height of a single line
|
S32 mLineHeight; // the max height of a single line
|
||||||
S32 mScrollLines; // how many lines we've scrolled down
|
S32 mScrollLines; // how many lines we've scrolled down
|
||||||
|
|||||||
@@ -312,7 +312,7 @@ void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file)
|
|||||||
// add objects as transient speakers that can be muted
|
// add objects as transient speakers that can be muted
|
||||||
if (chat.mSourceType == CHAT_SOURCE_OBJECT)
|
if (chat.mSourceType == CHAT_SOURCE_OBJECT)
|
||||||
{
|
{
|
||||||
LLLocalSpeakerMgr::getInstance()->setSpeaker(chat.mFromID, chat.mFromName, LLSpeaker::STATUS_NOT_IN_CHANNEL, LLSpeaker::SPEAKER_OBJECT);
|
LLLocalSpeakerMgr::getInstance()->setSpeaker({ chat.mFromID, LLSpeaker::SPEAKER_OBJECT, LLSpeaker::STATUS_NOT_IN_CHANNEL, boost::none, boost::none, chat.mFromName });
|
||||||
}
|
}
|
||||||
|
|
||||||
// start tab flashing on incoming text from other users (ignoring system text, etc)
|
// start tab flashing on incoming text from other users (ignoring system text, etc)
|
||||||
|
|||||||
@@ -60,11 +60,13 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source,
|
|||||||
mSpeakerMuteListener = new SpeakerMuteListener(*this);
|
mSpeakerMuteListener = new SpeakerMuteListener(*this);
|
||||||
mSpeakerBatchBeginListener = new SpeakerBatchBeginListener(*this);
|
mSpeakerBatchBeginListener = new SpeakerBatchBeginListener(*this);
|
||||||
mSpeakerBatchEndListener = new SpeakerBatchEndListener(*this);
|
mSpeakerBatchEndListener = new SpeakerBatchEndListener(*this);
|
||||||
|
mSpeakerSortingUpdateListener = new SpeakerSortingUpdateListener(*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(mSpeakerBatchBeginListener, "batch_begin");
|
||||||
mSpeakerMgr->addListener(mSpeakerBatchEndListener, "batch_end");
|
mSpeakerMgr->addListener(mSpeakerBatchEndListener, "batch_end");
|
||||||
|
mSpeakerMgr->addListener(mSpeakerSortingUpdateListener, "update_sorting");
|
||||||
//mSpeakerMgr->addListener(mSpeakerModeratorListener, "update_moderator");
|
//mSpeakerMgr->addListener(mSpeakerModeratorListener, "update_moderator");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,6 +231,11 @@ void LLParticipantList::handleSpeakerSelect()
|
|||||||
|
|
||||||
void LLParticipantList::refreshSpeakers()
|
void LLParticipantList::refreshSpeakers()
|
||||||
{
|
{
|
||||||
|
if (mUpdateTimer.getElapsedTimeF32() < .5f)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mUpdateTimer.reset();
|
||||||
// store off current selection and scroll state to preserve across list rebuilds
|
// store off current selection and scroll state to preserve across list rebuilds
|
||||||
const S32 scroll_pos = mAvatarList->getScrollInterface()->getScrollPos();
|
const S32 scroll_pos = mAvatarList->getScrollInterface()->getScrollPos();
|
||||||
|
|
||||||
@@ -239,27 +246,42 @@ void LLParticipantList::refreshSpeakers()
|
|||||||
// panel and hasn't been motionless for more than a few seconds. see DEV-6655 -MG
|
// panel and hasn't been motionless for more than a few seconds. see DEV-6655 -MG
|
||||||
LLRect screen_rect;
|
LLRect screen_rect;
|
||||||
localRectToScreen(getLocalRect(), &screen_rect);
|
localRectToScreen(getLocalRect(), &screen_rect);
|
||||||
mSpeakerMgr->update(!(screen_rect.pointInRect(gViewerWindow->getCurrentMouseX(), gViewerWindow->getCurrentMouseY()) && gMouseIdleTimer.getElapsedTimeF32() < 5.f));
|
bool resort_ok = !(screen_rect.pointInRect(gViewerWindow->getCurrentMouseX(), gViewerWindow->getCurrentMouseY()) && gMouseIdleTimer.getElapsedTimeF32() < 5.f);
|
||||||
|
mSpeakerMgr->update(resort_ok);
|
||||||
|
|
||||||
|
bool re_sort = false;
|
||||||
|
int start_pos = llmax(0, scroll_pos - 20);
|
||||||
|
int end_pos = scroll_pos + mAvatarList->getLinesPerPage() + 20;
|
||||||
std::vector<LLScrollListItem*> items = mAvatarList->getAllData();
|
std::vector<LLScrollListItem*> items = mAvatarList->getAllData();
|
||||||
|
if (start_pos >= items.size())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int count = 0;
|
||||||
for (std::vector<LLScrollListItem*>::iterator item_it = items.begin(); item_it != items.end(); ++item_it)
|
for (std::vector<LLScrollListItem*>::iterator item_it = items.begin(); item_it != items.end(); ++item_it)
|
||||||
{
|
{
|
||||||
|
|
||||||
LLScrollListItem* itemp = (*item_it);
|
LLScrollListItem* itemp = (*item_it);
|
||||||
LLPointer<LLSpeaker> speakerp = mSpeakerMgr->findSpeaker(itemp->getUUID());
|
LLPointer<LLSpeaker> speakerp = mSpeakerMgr->findSpeaker(itemp->getUUID());
|
||||||
if (speakerp.isNull()) continue;
|
if (speakerp.isNull()) continue;
|
||||||
|
|
||||||
if (LLScrollListCell* icon_cell = itemp->getColumn(0))
|
++count;
|
||||||
|
|
||||||
|
// Color changes. Only perform for rows that are near or in the viewable area.
|
||||||
|
if (count > start_pos && count <= end_pos)
|
||||||
{
|
{
|
||||||
if (speakerp->mStatus == LLSpeaker::STATUS_MUTED)
|
if (LLScrollListCell* icon_cell = itemp->getColumn(0))
|
||||||
{
|
{
|
||||||
icon_cell->setValue("mute_icon.tga");
|
if (speakerp->mStatus == LLSpeaker::STATUS_MUTED)
|
||||||
static const LLCachedControl<LLColor4> sAscentMutedColor("AscentMutedColor");
|
|
||||||
icon_cell->setColor(speakerp->mModeratorMutedVoice ? /*LLColor4::grey*/sAscentMutedColor : LLColor4(1.f, 71.f / 255.f, 71.f / 255.f, 1.f));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
switch(llmin(2, llfloor((speakerp->mSpeechVolume / LLVoiceClient::OVERDRIVEN_POWER_LEVEL) * 3.f)))
|
|
||||||
{
|
{
|
||||||
|
icon_cell->setValue("mute_icon.tga");
|
||||||
|
static const LLCachedControl<LLColor4> sAscentMutedColor("AscentMutedColor");
|
||||||
|
icon_cell->setColor(speakerp->mModeratorMutedVoice ? /*LLColor4::grey*/sAscentMutedColor : LLColor4(1.f, 71.f / 255.f, 71.f / 255.f, 1.f));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (llmin(2, llfloor((speakerp->mSpeechVolume / LLVoiceClient::OVERDRIVEN_POWER_LEVEL) * 3.f)))
|
||||||
|
{
|
||||||
case 0:
|
case 0:
|
||||||
icon_cell->setValue("icn_active-speakers-dot-lvl0.tga");
|
icon_cell->setValue("icn_active-speakers-dot-lvl0.tga");
|
||||||
break;
|
break;
|
||||||
@@ -269,62 +291,66 @@ void LLParticipantList::refreshSpeakers()
|
|||||||
case 2:
|
case 2:
|
||||||
icon_cell->setValue("icn_active-speakers-dot-lvl2.tga");
|
icon_cell->setValue("icn_active-speakers-dot-lvl2.tga");
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
// non voice speakers have hidden icons, render as transparent
|
||||||
|
icon_cell->setColor(speakerp->mStatus > LLSpeaker::STATUS_VOICE_ACTIVE ? LLColor4::transparent : speakerp->mDotColor);
|
||||||
}
|
}
|
||||||
// non voice speakers have hidden icons, render as transparent
|
|
||||||
icon_cell->setColor(speakerp->mStatus > LLSpeaker::STATUS_VOICE_ACTIVE ? LLColor4::transparent : speakerp->mDotColor);
|
|
||||||
}
|
}
|
||||||
}
|
// update name column
|
||||||
// update name column
|
if (LLScrollListCell* name_cell = itemp->getColumn(1))
|
||||||
if (LLScrollListCell* name_cell = itemp->getColumn(1))
|
|
||||||
{
|
|
||||||
if (speakerp->mStatus == LLSpeaker::STATUS_NOT_IN_CHANNEL)
|
|
||||||
{
|
{
|
||||||
// draw inactive speakers in different color
|
if (speakerp->mStatus == LLSpeaker::STATUS_NOT_IN_CHANNEL)
|
||||||
static const LLCachedControl<LLColor4> sSpeakersInactive(gColors, "SpeakersInactive");
|
|
||||||
name_cell->setColor(sSpeakersInactive);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// <edit>
|
|
||||||
bool found = mShowTextChatters || speakerp->mID == gAgentID;
|
|
||||||
const LLWorld::region_list_t& regions = LLWorld::getInstance()->getRegionList();
|
|
||||||
for (LLWorld::region_list_t::const_iterator iter = regions.begin(); !found && iter != regions.end(); ++iter)
|
|
||||||
{
|
{
|
||||||
// Are they in this sim?
|
// draw inactive speakers in different color
|
||||||
if (const LLViewerRegion* regionp = *iter)
|
static const LLCachedControl<LLColor4> sSpeakersInactive(gColors, "SpeakersInactive");
|
||||||
if (std::find(regionp->mMapAvatarIDs.begin(), regionp->mMapAvatarIDs.end(), speakerp->mID) != regionp->mMapAvatarIDs.end())
|
name_cell->setColor(sSpeakersInactive);
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
static const LLCachedControl<LLColor4> sSpeakersGhost(gColors, "SpeakersGhost");
|
|
||||||
name_cell->setColor(sSpeakersGhost);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
// </edit>
|
|
||||||
{
|
{
|
||||||
static const LLCachedControl<LLColor4> sDefaultListText(gColors, "DefaultListText");
|
// <edit>
|
||||||
name_cell->setColor(sDefaultListText);
|
bool found = mShowTextChatters || speakerp->mID == gAgentID;
|
||||||
|
const LLWorld::region_list_t& regions = LLWorld::getInstance()->getRegionList();
|
||||||
|
for (LLWorld::region_list_t::const_iterator iter = regions.begin(); !found && iter != regions.end(); ++iter)
|
||||||
|
{
|
||||||
|
// Are they in this sim?
|
||||||
|
if (const LLViewerRegion* regionp = *iter)
|
||||||
|
if (std::find(regionp->mMapAvatarIDs.begin(), regionp->mMapAvatarIDs.end(), speakerp->mID) != regionp->mMapAvatarIDs.end())
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
static const LLCachedControl<LLColor4> sSpeakersGhost(gColors, "SpeakersGhost");
|
||||||
|
name_cell->setColor(sSpeakersGhost);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
// </edit>
|
||||||
|
{
|
||||||
|
static const LLCachedControl<LLColor4> sDefaultListText(gColors, "DefaultListText");
|
||||||
|
name_cell->setColor(sDefaultListText);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// update name column. Need to update all rows to make name sorting behave correctly.
|
||||||
|
if (LLScrollListCell* name_cell = itemp->getColumn(1))
|
||||||
|
{
|
||||||
std::string speaker_name = speakerp->mDisplayName.empty() ? LLCacheName::getDefaultName() : speakerp->mDisplayName;
|
std::string speaker_name = speakerp->mDisplayName.empty() ? LLCacheName::getDefaultName() : speakerp->mDisplayName;
|
||||||
if (speakerp->mIsModerator)
|
if (speakerp->mIsModerator)
|
||||||
speaker_name += " " + getString("moderator_label");
|
speaker_name += " " + getString("moderator_label");
|
||||||
name_cell->setValue(speaker_name);
|
if (name_cell->getValue().asString() != speaker_name)
|
||||||
|
{
|
||||||
|
re_sort = true;
|
||||||
|
name_cell->setValue(speaker_name);
|
||||||
|
}
|
||||||
static_cast<LLScrollListText*>(name_cell)->setFontStyle(speakerp->mIsModerator ? LLFontGL::BOLD : LLFontGL::NORMAL);
|
static_cast<LLScrollListText*>(name_cell)->setFontStyle(speakerp->mIsModerator ? LLFontGL::BOLD : LLFontGL::NORMAL);
|
||||||
}
|
}
|
||||||
// update speaking order column
|
|
||||||
if (LLScrollListCell* speaking_status_cell = itemp->getColumn(2))
|
|
||||||
{
|
|
||||||
// since we are forced to sort by text, encode sort order as string
|
|
||||||
// print speaking ordinal in a text-sorting friendly manner
|
|
||||||
speaking_status_cell->setValue(llformat("%010d", speakerp->mSortIndex));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// we potentially modified the sort order by touching the list items
|
// we potentially modified the sort order by touching the list items
|
||||||
mAvatarList->setNeedsSort();
|
if (re_sort)
|
||||||
|
{
|
||||||
|
mAvatarList->setNeedsSortColumn(1);
|
||||||
|
}
|
||||||
|
|
||||||
// keep scroll value stable
|
// keep scroll value stable
|
||||||
mAvatarList->getScrollInterface()->setScrollPos(scroll_pos);
|
mAvatarList->getScrollInterface()->setScrollPos(scroll_pos);
|
||||||
@@ -391,6 +417,34 @@ void LLParticipantList::onSpeakerBatchEndEvent()
|
|||||||
mAvatarList->setSortEnabled(true);
|
mAvatarList->setSortEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LLParticipantList::onSpeakerSortingUpdateEvent()
|
||||||
|
{
|
||||||
|
bool re_sort = false;
|
||||||
|
for (auto&& item : mAvatarList->getAllData())
|
||||||
|
{
|
||||||
|
// update speaking order column
|
||||||
|
if (LLScrollListCell* speaking_status_cell = item->getColumn(2))
|
||||||
|
{
|
||||||
|
LLPointer<LLSpeaker> speakerp = mSpeakerMgr->findSpeaker(item->getUUID());
|
||||||
|
if (speakerp)
|
||||||
|
{
|
||||||
|
re_sort = true;
|
||||||
|
std::string sort_index = llformat("%010d", speakerp->mSortIndex);
|
||||||
|
// since we are forced to sort by text, encode sort order as string
|
||||||
|
// print speaking ordinal in a text-sorting friendly manner
|
||||||
|
if (speaking_status_cell->getValue().asString() != sort_index)
|
||||||
|
{
|
||||||
|
speaking_status_cell->setValue(sort_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (re_sort)
|
||||||
|
{
|
||||||
|
mAvatarList->setNeedsSortColumn(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
@@ -492,6 +546,12 @@ bool LLParticipantList::SpeakerBatchEndListener::handleEvent(LLPointer<LLOldEven
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LLParticipantList::SpeakerSortingUpdateListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
|
||||||
|
{
|
||||||
|
mParent.onSpeakerSortingUpdateEvent();
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ protected:
|
|||||||
bool onSpeakerMuteEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
|
bool onSpeakerMuteEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
|
||||||
void onSpeakerBatchBeginEvent();
|
void onSpeakerBatchBeginEvent();
|
||||||
void onSpeakerBatchEndEvent();
|
void onSpeakerBatchEndEvent();
|
||||||
|
void onSpeakerSortingUpdateEvent();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of listeners implementing LLOldEvents::LLSimpleListener.
|
* List of listeners implementing LLOldEvents::LLSimpleListener.
|
||||||
@@ -142,6 +143,13 @@ protected:
|
|||||||
/*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
|
/*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SpeakerSortingUpdateListener : public BaseSpeakerListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SpeakerSortingUpdateListener(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
|
||||||
@@ -212,6 +220,7 @@ private:
|
|||||||
LLSpeakerMgr* mSpeakerMgr;
|
LLSpeakerMgr* mSpeakerMgr;
|
||||||
LLScrollListCtrl* mAvatarList;
|
LLScrollListCtrl* mAvatarList;
|
||||||
bool mShowTextChatters;
|
bool mShowTextChatters;
|
||||||
|
LLFrameTimer mUpdateTimer;
|
||||||
|
|
||||||
LLPointer<SpeakerAddListener> mSpeakerAddListener;
|
LLPointer<SpeakerAddListener> mSpeakerAddListener;
|
||||||
LLPointer<SpeakerRemoveListener> mSpeakerRemoveListener;
|
LLPointer<SpeakerRemoveListener> mSpeakerRemoveListener;
|
||||||
@@ -220,6 +229,7 @@ private:
|
|||||||
LLPointer<SpeakerMuteListener> mSpeakerMuteListener;
|
LLPointer<SpeakerMuteListener> mSpeakerMuteListener;
|
||||||
LLPointer<SpeakerBatchBeginListener> mSpeakerBatchBeginListener;
|
LLPointer<SpeakerBatchBeginListener> mSpeakerBatchBeginListener;
|
||||||
LLPointer<SpeakerBatchEndListener> mSpeakerBatchEndListener;
|
LLPointer<SpeakerBatchEndListener> mSpeakerBatchEndListener;
|
||||||
|
LLPointer<SpeakerSortingUpdateListener> mSpeakerSortingUpdateListener;
|
||||||
|
|
||||||
validate_speaker_callback_t mValidateSpeakerCallback;
|
validate_speaker_callback_t mValidateSpeakerCallback;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -45,31 +45,54 @@
|
|||||||
const LLColor4 INACTIVE_COLOR(0.3f, 0.3f, 0.3f, 0.5f);
|
const LLColor4 INACTIVE_COLOR(0.3f, 0.3f, 0.3f, 0.5f);
|
||||||
const LLColor4 ACTIVE_COLOR(0.5f, 0.5f, 0.5f, 1.f);
|
const LLColor4 ACTIVE_COLOR(0.5f, 0.5f, 0.5f, 1.f);
|
||||||
|
|
||||||
LLSpeaker::LLSpeaker(const LLUUID& id, const std::string& name, const ESpeakerType type) :
|
LLSpeaker::LLSpeaker(const speaker_entry_t& entry) :
|
||||||
mStatus(LLSpeaker::STATUS_TEXT_ONLY),
|
mID(entry.id),
|
||||||
|
mStatus(entry.status),
|
||||||
|
mType(entry.type),
|
||||||
|
mIsModerator(entry.moderator != boost::none && *entry.moderator),
|
||||||
|
mModeratorMutedText(entry.moderator_muted_text != boost::none && *entry.moderator_muted_text),
|
||||||
|
mModeratorMutedVoice(FALSE),
|
||||||
mLastSpokeTime(0.f),
|
mLastSpokeTime(0.f),
|
||||||
mSpeechVolume(0.f),
|
mSpeechVolume(0.f),
|
||||||
mHasSpoken(FALSE),
|
mHasSpoken(FALSE),
|
||||||
mHasLeftCurrentCall(FALSE),
|
mHasLeftCurrentCall(FALSE),
|
||||||
mDotColor(LLColor4::white),
|
mDotColor(LLColor4::white),
|
||||||
mID(id),
|
|
||||||
mTyping(FALSE),
|
mTyping(FALSE),
|
||||||
mSortIndex(0),
|
mSortIndex(0),
|
||||||
mType(type),
|
mDisplayName(entry.name),
|
||||||
mIsModerator(FALSE),
|
mNeedsResort(true)
|
||||||
mModeratorMutedVoice(FALSE),
|
|
||||||
mModeratorMutedText(FALSE)
|
|
||||||
{
|
{
|
||||||
if (name.empty() && type == SPEAKER_AGENT)
|
if (mType == SPEAKER_AGENT)
|
||||||
{
|
{
|
||||||
lookupName();
|
lookupName();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
mDisplayName = name;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LLSpeaker::update(const speaker_entry_t& entry)
|
||||||
|
{
|
||||||
|
// keep highest priority status (lowest value) instead of overriding current value
|
||||||
|
setStatus(llmin(mStatus, entry.status));
|
||||||
|
if (entry.moderator != boost::none)
|
||||||
|
{
|
||||||
|
mIsModerator = *entry.moderator;
|
||||||
|
}
|
||||||
|
if (entry.moderator_muted_text != boost::none)
|
||||||
|
{
|
||||||
|
mModeratorMutedText = *entry.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 (entry.type == LLSpeaker::SPEAKER_AGENT)
|
||||||
|
{
|
||||||
|
mType = LLSpeaker::SPEAKER_AGENT;
|
||||||
|
lookupName();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mDisplayName.empty())
|
||||||
|
setName(entry.name);
|
||||||
|
}
|
||||||
|
|
||||||
void LLSpeaker::lookupName()
|
void LLSpeaker::lookupName()
|
||||||
{
|
{
|
||||||
@@ -77,7 +100,7 @@ void LLSpeaker::lookupName()
|
|||||||
{
|
{
|
||||||
// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Added: RLVa-1.0.0g
|
// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Added: RLVa-1.0.0g
|
||||||
if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES) && gAgentID != mID)
|
if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES) && gAgentID != mID)
|
||||||
mDisplayName = RlvStrings::getAnonym(mDisplayName);
|
setName(RlvStrings::getAnonym(mDisplayName));
|
||||||
else
|
else
|
||||||
// [/RLVa:KB]
|
// [/RLVa:KB]
|
||||||
LLAvatarNameCache::get(mID, boost::bind(&LLSpeaker::onNameCache, this, _2));
|
LLAvatarNameCache::get(mID, boost::bind(&LLSpeaker::onNameCache, this, _2));
|
||||||
@@ -88,9 +111,9 @@ void LLSpeaker::onNameCache(const LLAvatarName& full_name)
|
|||||||
{
|
{
|
||||||
static const LLCachedControl<S32> name_system("SpeakerNameSystem");
|
static const LLCachedControl<S32> name_system("SpeakerNameSystem");
|
||||||
if (!name_system)
|
if (!name_system)
|
||||||
mDisplayName = gCacheName->cleanFullName(full_name.getLegacyName());
|
setName(gCacheName->cleanFullName(full_name.getLegacyName()));
|
||||||
else
|
else
|
||||||
mDisplayName = full_name.getNSName(name_system);
|
setName(full_name.getNSName(name_system));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LLSpeaker::isInVoiceChannel()
|
bool LLSpeaker::isInVoiceChannel()
|
||||||
@@ -200,7 +223,7 @@ BOOL LLSpeakerActionTimer::tick()
|
|||||||
|
|
||||||
void LLSpeakerActionTimer::unset()
|
void LLSpeakerActionTimer::unset()
|
||||||
{
|
{
|
||||||
mActionCallback = NULL;
|
mActionCallback = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
LLSpeakersDelayActionsStorage::LLSpeakersDelayActionsStorage(LLSpeakerActionTimer::action_callback_t action_cb, F32 action_delay)
|
LLSpeakersDelayActionsStorage::LLSpeakersDelayActionsStorage(LLSpeakerActionTimer::action_callback_t action_cb, F32 action_delay)
|
||||||
@@ -338,22 +361,23 @@ LLSpeakerMgr::~LLSpeakerMgr()
|
|||||||
delete mSpeakerDelayRemover;
|
delete mSpeakerDelayRemover;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLSpeakerMgr::setSpeakers(const std::vector<LLSpeakerMgr::speaker_entry_t>& speakers)
|
void LLSpeakerMgr::setSpeakers(const std::vector<speaker_entry_t>& speakers)
|
||||||
{
|
{
|
||||||
if (!speakers.empty())
|
if (!speakers.empty())
|
||||||
{
|
{
|
||||||
fireEvent(new LLOldEvents::LLEvent(this), "batch_begin");
|
fireEvent(new LLOldEvents::LLEvent(this), "batch_begin");
|
||||||
for (auto entry : speakers)
|
for (auto entry : speakers)
|
||||||
{
|
{
|
||||||
setSpeaker(entry.id, entry.name, entry.status, entry.type, entry.moderator, entry.moderator_muted_text);
|
setSpeaker(entry);
|
||||||
}
|
}
|
||||||
fireEvent(new LLOldEvents::LLEvent(this), "batch_end");
|
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)
|
LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const speaker_entry_t& entry)
|
||||||
{
|
{
|
||||||
LLUUID session_id = getSessionID();
|
LLUUID session_id = getSessionID();
|
||||||
|
const LLUUID& id = entry.id;
|
||||||
if (id.isNull() || (id == session_id))
|
if (id.isNull() || (id == session_id))
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -363,38 +387,16 @@ LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::strin
|
|||||||
auto it = mSpeakers.find(id);
|
auto it = mSpeakers.find(id);
|
||||||
if (it == mSpeakers.end() || it->second.isNull())
|
if (it == mSpeakers.end() || it->second.isNull())
|
||||||
{
|
{
|
||||||
speakerp = new LLSpeaker(id, name, type);
|
mSpeakersSorted.emplace_back(new LLSpeaker(entry));
|
||||||
speakerp->mStatus = status;
|
mSpeakers.emplace(id, mSpeakersSorted.back());
|
||||||
speakerp->mIsModerator = moderator;
|
fireEvent(new LLSpeakerListChangeEvent(this, id), "add");
|
||||||
speakerp->mModeratorMutedText = moderator_muted_text;
|
|
||||||
mSpeakers.insert(std::make_pair(speakerp->mID, speakerp));
|
|
||||||
mSpeakersSorted.push_back(speakerp);
|
|
||||||
fireEvent(new LLSpeakerListChangeEvent(this, speakerp->mID), "add");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
speakerp = it->second;
|
it->second->update(entry);
|
||||||
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)
|
|
||||||
{
|
|
||||||
speakerp->mType = LLSpeaker::SPEAKER_AGENT;
|
|
||||||
speakerp->lookupName();
|
|
||||||
}
|
|
||||||
if (update_moderator)
|
|
||||||
{
|
|
||||||
fireEvent(new LLSpeakerUpdateModeratorEvent(speakerp), "update_moderator");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mSpeakerDelayRemover->unsetActionTimer(speakerp->mID);
|
mSpeakerDelayRemover->unsetActionTimer(entry.id);
|
||||||
return speakerp;
|
return speakerp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -442,7 +444,8 @@ void LLSpeakerMgr::update(BOOL resort_ok)
|
|||||||
|
|
||||||
// update status of all current speakers
|
// update status of all current speakers
|
||||||
BOOL voice_channel_active = (!mVoiceChannel && LLVoiceClient::getInstance()->inProximalChannel()) || (mVoiceChannel && mVoiceChannel->isActive());
|
BOOL voice_channel_active = (!mVoiceChannel && LLVoiceClient::getInstance()->inProximalChannel()) || (mVoiceChannel && mVoiceChannel->isActive());
|
||||||
for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); speaker_it++)
|
bool re_sort = false;
|
||||||
|
for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); ++speaker_it)
|
||||||
{
|
{
|
||||||
LLUUID speaker_id = speaker_it->first;
|
LLUUID speaker_id = speaker_it->first;
|
||||||
LLSpeaker* speakerp = speaker_it->second;
|
LLSpeaker* speakerp = speaker_it->second;
|
||||||
@@ -450,7 +453,7 @@ void LLSpeakerMgr::update(BOOL resort_ok)
|
|||||||
if (voice_channel_active && LLVoiceClient::getInstance()->getVoiceEnabled(speaker_id))
|
if (voice_channel_active && LLVoiceClient::getInstance()->getVoiceEnabled(speaker_id))
|
||||||
{
|
{
|
||||||
speakerp->mSpeechVolume = LLVoiceClient::getInstance()->getCurrentPower(speaker_id);
|
speakerp->mSpeechVolume = LLVoiceClient::getInstance()->getCurrentPower(speaker_id);
|
||||||
BOOL moderator_muted_voice = LLVoiceClient::getInstance()->getIsModeratorMuted(speaker_id);
|
bool moderator_muted_voice = LLVoiceClient::getInstance()->getIsModeratorMuted(speaker_id);
|
||||||
if (moderator_muted_voice != speakerp->mModeratorMutedVoice)
|
if (moderator_muted_voice != speakerp->mModeratorMutedVoice)
|
||||||
{
|
{
|
||||||
speakerp->mModeratorMutedVoice = moderator_muted_voice;
|
speakerp->mModeratorMutedVoice = moderator_muted_voice;
|
||||||
@@ -460,18 +463,18 @@ void LLSpeakerMgr::update(BOOL resort_ok)
|
|||||||
|
|
||||||
if (LLVoiceClient::getInstance()->getOnMuteList(speaker_id) || speakerp->mModeratorMutedVoice)
|
if (LLVoiceClient::getInstance()->getOnMuteList(speaker_id) || speakerp->mModeratorMutedVoice)
|
||||||
{
|
{
|
||||||
speakerp->mStatus = LLSpeaker::STATUS_MUTED;
|
speakerp->setStatus(LLSpeaker::STATUS_MUTED);
|
||||||
}
|
}
|
||||||
else if (LLVoiceClient::getInstance()->getIsSpeaking(speaker_id))
|
else if (LLVoiceClient::getInstance()->getIsSpeaking(speaker_id))
|
||||||
{
|
{
|
||||||
// reset inactivity expiration
|
// reset inactivity expiration
|
||||||
if (speakerp->mStatus != LLSpeaker::STATUS_SPEAKING)
|
if (speakerp->mStatus != LLSpeaker::STATUS_SPEAKING)
|
||||||
{
|
{
|
||||||
speakerp->mLastSpokeTime = mSpeechTimer.getElapsedTimeF32();
|
speakerp->setSpokenTime(mSpeechTimer.getElapsedTimeF32());
|
||||||
speakerp->mHasSpoken = TRUE;
|
speakerp->mHasSpoken = TRUE;
|
||||||
fireEvent(new LLSpeakerUpdateSpeakerEvent(speakerp), "update_speaker");
|
fireEvent(new LLSpeakerUpdateSpeakerEvent(speakerp), "update_speaker");
|
||||||
}
|
}
|
||||||
speakerp->mStatus = LLSpeaker::STATUS_SPEAKING;
|
speakerp->setStatus(LLSpeaker::STATUS_SPEAKING);
|
||||||
// interpolate between active color and full speaking color based on power of speech output
|
// interpolate between active color and full speaking color based on power of speech output
|
||||||
speakerp->mDotColor = speaking_color;
|
speakerp->mDotColor = speaking_color;
|
||||||
if (speakerp->mSpeechVolume > LLVoiceClient::OVERDRIVEN_POWER_LEVEL)
|
if (speakerp->mSpeechVolume > LLVoiceClient::OVERDRIVEN_POWER_LEVEL)
|
||||||
@@ -487,12 +490,12 @@ void LLSpeakerMgr::update(BOOL resort_ok)
|
|||||||
if (speakerp->mHasSpoken)
|
if (speakerp->mHasSpoken)
|
||||||
{
|
{
|
||||||
// have spoken once, not currently speaking
|
// have spoken once, not currently speaking
|
||||||
speakerp->mStatus = LLSpeaker::STATUS_HAS_SPOKEN;
|
speakerp->setStatus(LLSpeaker::STATUS_HAS_SPOKEN);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// default state for being in voice channel
|
// default state for being in voice channel
|
||||||
speakerp->mStatus = LLSpeaker::STATUS_VOICE_ACTIVE;
|
speakerp->setStatus(LLSpeaker::STATUS_VOICE_ACTIVE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -506,39 +509,53 @@ void LLSpeakerMgr::update(BOOL resort_ok)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
speakerp->mStatus = LLSpeaker::STATUS_TEXT_ONLY;
|
speakerp->setStatus(LLSpeaker::STATUS_TEXT_ONLY);
|
||||||
speakerp->mSpeechVolume = 0.f;
|
speakerp->mSpeechVolume = 0.f;
|
||||||
speakerp->mDotColor = ACTIVE_COLOR;
|
speakerp->mDotColor = ACTIVE_COLOR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (speakerp->mNeedsResort)
|
||||||
|
{
|
||||||
|
re_sort = true;
|
||||||
|
speakerp->mNeedsResort = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(resort_ok) // only allow list changes when user is not interacting with it
|
if (resort_ok && re_sort) // only allow list changes when user is not interacting with it
|
||||||
{
|
{
|
||||||
// sort by status then time last spoken
|
// sort by status then time last spoken
|
||||||
std::sort(mSpeakersSorted.begin(), mSpeakersSorted.end(), LLSortRecentSpeakers());
|
std::sort(mSpeakersSorted.begin(), mSpeakersSorted.end(), LLSortRecentSpeakers());
|
||||||
}
|
|
||||||
|
|
||||||
// for recent speakers who are not currently speaking, show "recent" color dot for most recent
|
// for recent speakers who are not currently speaking, show "recent" color dot for most recent
|
||||||
// fading to "active" color
|
// fading to "active" color
|
||||||
|
|
||||||
S32 recent_speaker_count = 0;
|
bool index_changed = false;
|
||||||
S32 sort_index = 0;
|
S32 recent_speaker_count = 0;
|
||||||
speaker_list_t::iterator sorted_speaker_it;
|
S32 sort_index = 0;
|
||||||
for(sorted_speaker_it = mSpeakersSorted.begin();
|
for (speaker_list_t::iterator sorted_speaker_it = mSpeakersSorted.begin();
|
||||||
sorted_speaker_it != mSpeakersSorted.end(); ++sorted_speaker_it)
|
sorted_speaker_it != mSpeakersSorted.end();
|
||||||
{
|
++sorted_speaker_it)
|
||||||
LLPointer<LLSpeaker> speakerp = *sorted_speaker_it;
|
|
||||||
|
|
||||||
// color code recent speakers who are not currently speaking
|
|
||||||
if (speakerp->mStatus == LLSpeaker::STATUS_HAS_SPOKEN)
|
|
||||||
{
|
{
|
||||||
speakerp->mDotColor = lerp(speaking_color, ACTIVE_COLOR, clamp_rescale((F32)recent_speaker_count, -2.f, 3.f, 0.f, 1.f));
|
LLPointer<LLSpeaker> speakerp = *sorted_speaker_it;
|
||||||
recent_speaker_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// stuff sort ordinal into speaker so the ui can sort by this value
|
// color code recent speakers who are not currently speaking
|
||||||
speakerp->mSortIndex = sort_index++;
|
if (speakerp->mStatus == LLSpeaker::STATUS_HAS_SPOKEN)
|
||||||
|
{
|
||||||
|
speakerp->mDotColor = lerp(speaking_color, ACTIVE_COLOR, clamp_rescale((F32)recent_speaker_count, -2.f, 3.f, 0.f, 1.f));
|
||||||
|
recent_speaker_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// stuff sort ordinal into speaker so the ui can sort by this value
|
||||||
|
if (speakerp->mSortIndex != sort_index++)
|
||||||
|
{
|
||||||
|
speakerp->mSortIndex = sort_index-1;
|
||||||
|
index_changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (index_changed)
|
||||||
|
{
|
||||||
|
fireEvent(new LLOldEvents::LLEvent(this), "update_sorting");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -554,11 +571,13 @@ void LLSpeakerMgr::updateSpeakerList()
|
|||||||
speakers.reserve(participants.size());
|
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)
|
||||||
{
|
{
|
||||||
speakers.emplace_back(speaker_entry_t(
|
speakers.emplace_back(
|
||||||
*participant_it,
|
*participant_it,
|
||||||
|
(LLVoiceClient::getInstance()->isParticipantAvatar(*participant_it) ? LLSpeaker::SPEAKER_AGENT : LLSpeaker::SPEAKER_EXTERNAL),
|
||||||
LLSpeaker::STATUS_VOICE_ACTIVE,
|
LLSpeaker::STATUS_VOICE_ACTIVE,
|
||||||
LLVoiceClient::getInstance()->getDisplayName(*participant_it),
|
boost::none,
|
||||||
(LLVoiceClient::getInstance()->isParticipantAvatar(*participant_it)?LLSpeaker::SPEAKER_AGENT:LLSpeaker::SPEAKER_EXTERNAL)));
|
boost::none,
|
||||||
|
LLVoiceClient::getInstance()->getDisplayName(*participant_it));
|
||||||
}
|
}
|
||||||
setSpeakers(speakers);
|
setSpeakers(speakers);
|
||||||
}
|
}
|
||||||
@@ -602,12 +621,11 @@ 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()))
|
||||||
{
|
{
|
||||||
speakers.emplace_back(speaker_entry_t(
|
speakers.emplace_back(
|
||||||
id,
|
id,
|
||||||
LLSpeaker::STATUS_VOICE_ACTIVE,
|
|
||||||
"",
|
|
||||||
LLSpeaker::SPEAKER_AGENT,
|
LLSpeaker::SPEAKER_AGENT,
|
||||||
(member->getAgentPowers() & GP_SESSION_MODERATOR) == GP_SESSION_MODERATOR));
|
LLSpeaker::STATUS_VOICE_ACTIVE,
|
||||||
|
(member->getAgentPowers() & GP_SESSION_MODERATOR) == GP_SESSION_MODERATOR);
|
||||||
}
|
}
|
||||||
++member_it;
|
++member_it;
|
||||||
}
|
}
|
||||||
@@ -638,12 +656,12 @@ 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);
|
setSpeaker({ gAgentID, LLSpeaker::SPEAKER_AGENT, LLSpeaker::STATUS_VOICE_ACTIVE });
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLSpeakerMgr::setSpeakerNotInChannel(LLSpeaker* speakerp)
|
void LLSpeakerMgr::setSpeakerNotInChannel(LLSpeaker* speakerp)
|
||||||
{
|
{
|
||||||
speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
|
speakerp->setStatus(LLSpeaker::STATUS_NOT_IN_CHANNEL);
|
||||||
speakerp->mDotColor = INACTIVE_COLOR;
|
speakerp->mDotColor = INACTIVE_COLOR;
|
||||||
mSpeakerDelayRemover->setActionTimer(speakerp->mID);
|
mSpeakerDelayRemover->setActionTimer(speakerp->mID);
|
||||||
}
|
}
|
||||||
@@ -723,7 +741,7 @@ void LLSpeakerMgr::speakerChatted(const LLUUID& speaker_id)
|
|||||||
LLPointer<LLSpeaker> speakerp = findSpeaker(speaker_id);
|
LLPointer<LLSpeaker> speakerp = findSpeaker(speaker_id);
|
||||||
if (speakerp.notNull())
|
if (speakerp.notNull())
|
||||||
{
|
{
|
||||||
speakerp->mLastSpokeTime = mSpeechTimer.getElapsedTimeF32();
|
speakerp->setSpokenTime(mSpeechTimer.getElapsedTimeF32());
|
||||||
speakerp->mHasSpoken = TRUE;
|
speakerp->mHasSpoken = TRUE;
|
||||||
fireEvent(new LLSpeakerUpdateSpeakerEvent(speakerp), "update_speaker");
|
fireEvent(new LLSpeakerUpdateSpeakerEvent(speakerp), "update_speaker");
|
||||||
}
|
}
|
||||||
@@ -766,8 +784,8 @@ void LLIMSpeakerMgr::setSpeakers(const LLSD& speakers)
|
|||||||
speaker_it != speakers["agent_info"].endMap();
|
speaker_it != speakers["agent_info"].endMap();
|
||||||
++speaker_it)
|
++speaker_it)
|
||||||
{
|
{
|
||||||
bool moderator = false;
|
boost::optional<bool> moderator;
|
||||||
bool moderator_muted = false;
|
boost::optional<bool> moderator_muted;
|
||||||
if (speaker_it->second.isMap())
|
if (speaker_it->second.isMap())
|
||||||
{
|
{
|
||||||
moderator = speaker_it->second["is_moderator"];
|
moderator = speaker_it->second["is_moderator"];
|
||||||
@@ -775,9 +793,8 @@ void LLIMSpeakerMgr::setSpeakers(const LLSD& speakers)
|
|||||||
}
|
}
|
||||||
speakerentries.emplace_back(
|
speakerentries.emplace_back(
|
||||||
LLUUID(speaker_it->first),
|
LLUUID(speaker_it->first),
|
||||||
LLSpeaker::STATUS_TEXT_ONLY,
|
|
||||||
"",
|
|
||||||
LLSpeaker::SPEAKER_AGENT,
|
LLSpeaker::SPEAKER_AGENT,
|
||||||
|
LLSpeaker::STATUS_TEXT_ONLY,
|
||||||
moderator,
|
moderator,
|
||||||
moderator_muted
|
moderator_muted
|
||||||
);
|
);
|
||||||
@@ -816,8 +833,8 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
|
|||||||
LLPointer<LLSpeaker> speakerp = findSpeaker(agent_id);
|
LLPointer<LLSpeaker> speakerp = findSpeaker(agent_id);
|
||||||
|
|
||||||
bool new_speaker = false;
|
bool new_speaker = false;
|
||||||
bool moderator = false;
|
boost::optional<bool> moderator;
|
||||||
bool moderator_muted = false;
|
boost::optional<bool> moderator_muted_text;
|
||||||
|
|
||||||
LLSD agent_data = update_it->second;
|
LLSD agent_data = update_it->second;
|
||||||
if (agent_data.isMap() && agent_data.has("transition"))
|
if (agent_data.isMap() && agent_data.has("transition"))
|
||||||
@@ -852,16 +869,15 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
|
|||||||
}
|
}
|
||||||
if (agent_info.has("mutes"))
|
if (agent_info.has("mutes"))
|
||||||
{
|
{
|
||||||
moderator_muted = agent_info["mutes"]["text"];
|
moderator_muted_text = agent_info["mutes"]["text"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
speakerentries.emplace_back(
|
speakerentries.emplace_back(
|
||||||
agent_id,
|
agent_id,
|
||||||
LLSpeaker::STATUS_TEXT_ONLY,
|
|
||||||
"",
|
|
||||||
LLSpeaker::SPEAKER_AGENT,
|
LLSpeaker::SPEAKER_AGENT,
|
||||||
|
LLSpeaker::STATUS_TEXT_ONLY,
|
||||||
moderator,
|
moderator,
|
||||||
moderator_muted
|
moderator_muted_text
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -884,9 +900,7 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
|
|||||||
else if ( agent_transition == "ENTER")
|
else if ( agent_transition == "ENTER")
|
||||||
{
|
{
|
||||||
// add or update speaker
|
// add or update speaker
|
||||||
speakerentries.emplace_back(
|
speakerentries.emplace_back(agent_id);
|
||||||
agent_id
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1074,8 +1088,8 @@ void LLLocalSpeakerMgr::updateSpeakerList()
|
|||||||
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)
|
||||||
{
|
{
|
||||||
LLUUID speaker_id = speaker_it->first;
|
LLUUID speaker_id = speaker_it->first;
|
||||||
LLSpeaker* speakerp = speaker_it->second;
|
LLPointer<LLSpeaker> speakerp = speaker_it->second;
|
||||||
if (speakerp && speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY)
|
if (speakerp.notNull() && speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY)
|
||||||
{
|
{
|
||||||
LLVOAvatar* avatarp = gObjectList.findAvatar(speaker_id);
|
LLVOAvatar* avatarp = gObjectList.findAvatar(speaker_id);
|
||||||
if (!avatarp || dist_vec_squared(avatarp->getPositionAgent(), gAgent.getPositionAgent()) > CHAT_NORMAL_RADIUS * CHAT_NORMAL_RADIUS)
|
if (!avatarp || dist_vec_squared(avatarp->getPositionAgent(), gAgent.getPositionAgent()) > CHAT_NORMAL_RADIUS * CHAT_NORMAL_RADIUS)
|
||||||
|
|||||||
@@ -56,29 +56,78 @@ public:
|
|||||||
STATUS_MUTED
|
STATUS_MUTED
|
||||||
} ESpeakerStatus;
|
} ESpeakerStatus;
|
||||||
|
|
||||||
|
struct speaker_entry_t
|
||||||
|
{
|
||||||
|
speaker_entry_t(const LLUUID& id,
|
||||||
|
LLSpeaker::ESpeakerType type = ESpeakerType::SPEAKER_AGENT,
|
||||||
|
LLSpeaker::ESpeakerStatus status = ESpeakerStatus::STATUS_TEXT_ONLY,
|
||||||
|
const boost::optional<bool> moderator = boost::none,
|
||||||
|
const boost::optional<bool> moderator_muted_text = boost::none,
|
||||||
|
std::string name = std::string()) :
|
||||||
|
id(id),
|
||||||
|
type(type),
|
||||||
|
status(status),
|
||||||
|
moderator(moderator),
|
||||||
|
moderator_muted_text(moderator_muted_text),
|
||||||
|
name(name)
|
||||||
|
{}
|
||||||
|
const LLUUID id;
|
||||||
|
const LLSpeaker::ESpeakerType type;
|
||||||
|
const LLSpeaker::ESpeakerStatus status;
|
||||||
|
const boost::optional<bool> moderator;
|
||||||
|
const boost::optional<bool> moderator_muted_text;
|
||||||
|
const std::string name;
|
||||||
|
};
|
||||||
|
|
||||||
LLSpeaker(const LLUUID& id, const std::string& name = LLStringUtil::null, const ESpeakerType type = SPEAKER_AGENT);
|
LLSpeaker(const speaker_entry_t& entry);
|
||||||
~LLSpeaker() {};
|
~LLSpeaker() {};
|
||||||
|
void update(const speaker_entry_t& entry);
|
||||||
void lookupName();
|
void lookupName();
|
||||||
|
|
||||||
void onNameCache(const LLAvatarName& full_name);
|
void onNameCache(const LLAvatarName& full_name);
|
||||||
|
|
||||||
bool isInVoiceChannel();
|
bool isInVoiceChannel();
|
||||||
|
|
||||||
|
void setStatus(ESpeakerStatus status)
|
||||||
|
{
|
||||||
|
if (status != mStatus)
|
||||||
|
{
|
||||||
|
mStatus = status;
|
||||||
|
mNeedsResort = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void setName(const std::string& name)
|
||||||
|
{
|
||||||
|
if (name != mDisplayName)
|
||||||
|
{
|
||||||
|
mDisplayName = name;
|
||||||
|
mNeedsResort = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void setSpokenTime(F32 time)
|
||||||
|
{
|
||||||
|
if (mLastSpokeTime != time)
|
||||||
|
{
|
||||||
|
mLastSpokeTime = time;
|
||||||
|
mNeedsResort = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LLUUID mID;
|
||||||
ESpeakerStatus mStatus; // current activity status in speech group
|
ESpeakerStatus mStatus; // current activity status in speech group
|
||||||
|
ESpeakerType mType : 2;
|
||||||
|
bool mIsModerator : 1;
|
||||||
|
bool mModeratorMutedVoice : 1;
|
||||||
|
bool mModeratorMutedText : 1;
|
||||||
|
bool mHasSpoken : 1; // has this speaker said anything this session?
|
||||||
|
bool mHasLeftCurrentCall : 1; // has this speaker left the current voice call?
|
||||||
|
bool mTyping : 1;
|
||||||
F32 mLastSpokeTime; // timestamp when this speaker last spoke
|
F32 mLastSpokeTime; // timestamp when this speaker last spoke
|
||||||
F32 mSpeechVolume; // current speech amplitude (timea average rms amplitude?)
|
F32 mSpeechVolume; // current speech amplitude (timea average rms amplitude?)
|
||||||
std::string mDisplayName; // cache user name for this speaker
|
std::string mDisplayName; // cache user name for this speaker
|
||||||
BOOL mHasSpoken; // has this speaker said anything this session?
|
|
||||||
BOOL mHasLeftCurrentCall; // has this speaker left the current voice call?
|
|
||||||
LLColor4 mDotColor;
|
LLColor4 mDotColor;
|
||||||
LLUUID mID;
|
bool mNeedsResort;
|
||||||
BOOL mTyping;
|
|
||||||
S32 mSortIndex;
|
S32 mSortIndex;
|
||||||
ESpeakerType mType;
|
|
||||||
BOOL mIsModerator;
|
|
||||||
BOOL mModeratorMutedVoice;
|
|
||||||
BOOL mModeratorMutedText;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class LLSpeakerUpdateSpeakerEvent : public LLOldEvents::LLEvent
|
class LLSpeakerUpdateSpeakerEvent : public LLOldEvents::LLEvent
|
||||||
@@ -137,7 +186,7 @@ private:
|
|||||||
class LLSpeakerActionTimer : public LLEventTimer
|
class LLSpeakerActionTimer : public LLEventTimer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef boost::function<bool(const LLUUID&)> action_callback_t;
|
typedef std::function<bool(const LLUUID&)> action_callback_t;
|
||||||
typedef std::map<LLUUID, LLSpeakerActionTimer*> action_timers_map_t;
|
typedef std::map<LLUUID, LLSpeakerActionTimer*> action_timers_map_t;
|
||||||
typedef action_timers_map_t::value_type action_value_t;
|
typedef action_timers_map_t::value_type action_value_t;
|
||||||
typedef action_timers_map_t::const_iterator action_timer_const_iter_t;
|
typedef action_timers_map_t::const_iterator action_timer_const_iter_t;
|
||||||
@@ -223,6 +272,8 @@ class LLSpeakerMgr : public LLOldEvents::LLObservable
|
|||||||
LOG_CLASS(LLSpeakerMgr);
|
LOG_CLASS(LLSpeakerMgr);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
typedef LLSpeaker::speaker_entry_t speaker_entry_t;
|
||||||
|
|
||||||
LLSpeakerMgr(LLVoiceChannel* channelp);
|
LLSpeakerMgr(LLVoiceChannel* channelp);
|
||||||
virtual ~LLSpeakerMgr();
|
virtual ~LLSpeakerMgr();
|
||||||
|
|
||||||
@@ -231,31 +282,8 @@ public:
|
|||||||
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);
|
void setSpeakers(const std::vector<speaker_entry_t>& speakers);
|
||||||
LLPointer<LLSpeaker> setSpeaker(const LLUUID& id,
|
LLPointer<LLSpeaker> setSpeaker(const speaker_entry_t& speakers);
|
||||||
const std::string& name = LLStringUtil::null,
|
|
||||||
LLSpeaker::ESpeakerStatus status = LLSpeaker::STATUS_TEXT_ONLY,
|
|
||||||
LLSpeaker::ESpeakerType = LLSpeaker::SPEAKER_AGENT,
|
|
||||||
bool moderator = false,
|
|
||||||
bool moderator_muted_text = false);
|
|
||||||
|
|
||||||
BOOL isVoiceActive();
|
BOOL isVoiceActive();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user