diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index 462d781dc02167eea1314b283fee9bdf99fa4013..e334a4eeba7066c2c9f7f1d596f6ff5f790b1ff3 100755 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -36,6 +36,7 @@ #include "lltextutil.h" // newview +#include "llagent.h" #include "llagentdata.h" // for comparator #include "llavatariconctrl.h" #include "llavatarnamecache.h" @@ -47,11 +48,12 @@ #include "llvoiceclient.h" #include "llviewercontrol.h" // for gSavedSettings #include "lltooldraganddrop.h" +#include "llworld.h" static LLDefaultChildRegistry::Register<LLAvatarList> r("avatar_list"); // Last interaction time update period. -static const F32 LIT_UPDATE_PERIOD = 5; +static const F32 LIT_UPDATE_PERIOD = 2; // Maximum number of avatars that can be added to a list in one pass. // Used to limit time spent for avatar list update per frame. @@ -120,6 +122,7 @@ static const LLFlatListView::ItemReverseComparator REVERSE_NAME_COMPARATOR(NAME_ LLAvatarList::Params::Params() : ignore_online_status("ignore_online_status", false) , show_last_interaction_time("show_last_interaction_time", false) +, show_distance("show_distance", false) , show_info_btn("show_info_btn", true) , show_profile_btn("show_profile_btn", true) , show_speaking_indicator("show_speaking_indicator", true) @@ -131,6 +134,7 @@ LLAvatarList::LLAvatarList(const Params& p) : LLFlatListViewEx(p) , mIgnoreOnlineStatus(p.ignore_online_status) , mShowLastInteractionTime(p.show_last_interaction_time) +, mShowDistance(p.show_distance) , mContextMenu(NULL) , mDirty(true) // to force initial update , mNeedUpdateNames(false) @@ -146,7 +150,7 @@ LLAvatarList::LLAvatarList(const Params& p) // Set default sort order. setComparator(&NAME_COMPARATOR); - if (mShowLastInteractionTime) + if (mShowLastInteractionTime || mShowDistance) { mLITUpdateTimer = new LLTimer(); mLITUpdateTimer->setTimerExpirySec(0); // zero to force initial update @@ -198,6 +202,11 @@ void LLAvatarList::draw() updateLastInteractionTimes(); mLITUpdateTimer->setTimerExpirySec(LIT_UPDATE_PERIOD); // restart the timer } + else if (mShowDistance && mLITUpdateTimer->hasExpired()) + { + updateDistances(); + mLITUpdateTimer->setTimerExpirySec(LIT_UPDATE_PERIOD); + } } //virtual @@ -245,6 +254,7 @@ void LLAvatarList::addAvalineItem(const LLUUID& item_id, const LLUUID& session_i item->setAvatarId(item_id, session_id, true, false); item->setName(item_name); item->showLastInteractionTime(mShowLastInteractionTime); + item->showDistance(mShowDistance); item->showSpeakingIndicator(mShowSpeakingIndicator); item->setOnline(false); @@ -441,6 +451,7 @@ void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is item->setAvatarId(id, mSessionID, mIgnoreOnlineStatus); item->setOnline(mIgnoreOnlineStatus ? true : is_online); item->showLastInteractionTime(mShowLastInteractionTime); + item->showDistance(mShowDistance); item->setAvatarIconVisible(mShowIcons); item->setShowInfoBtn(mShowInfoBtn); @@ -577,6 +588,26 @@ void LLAvatarList::updateLastInteractionTimes() } } +void LLAvatarList::updateDistances() +{ + std::vector<LLPanel*> items; + getItems(items); + + for(std::vector<LLPanel*>::const_iterator it = items.begin(); it != items.end(); ++it) + { + LLAvatarListItem* item = static_cast<LLAvatarListItem*>(*it); + if (item->getAvatarId() == gAgentID) continue; + + boost::unordered_map<LLUUID, LLVector3d> positions; + LLWorld::getInstance()->getAvatars(&positions, gAgent.getPositionGlobal(), gSavedSettings.getF32("NearMeRange")); + boost::unordered_map<LLUUID, LLVector3d>::iterator iter = positions.find(item->getAvatarId()); + if (iter != positions.end()) + item->setDistance((iter->second - gAgent.getPositionGlobal()).magVec()); + else + item->setDistance(0); + } +} + void LLAvatarList::onItemDoubleClicked(LLUICtrl* ctrl, S32 x, S32 y, MASK mask) { mItemDoubleClickSignal(ctrl, x, y, mask); @@ -639,6 +670,7 @@ BOOL LLAvalineListItem::postBuild() { setOnline(true); showLastInteractionTime(false); + showDistance(false); setShowProfileBtn(false); setShowInfoBtn(false); mAvatarIcon->setValue("Avaline_Icon"); diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h index 3542577ae3c3f7cfb89272fdf1968624c0bd576f..080d4dd28dcccbce12cb19ac97c3c51acf96b181 100755 --- a/indra/newview/llavatarlist.h +++ b/indra/newview/llavatarlist.h @@ -51,6 +51,7 @@ public: { Optional<bool> ignore_online_status, // show all items as online show_last_interaction_time, // show most recent interaction time. *HACK: move this to a derived class + show_distance, // *HACK: my sinuses hurt and i want pizza. show_info_btn, show_profile_btn, show_speaking_indicator, @@ -69,7 +70,7 @@ public: void setNameFilter(const std::string& filter); void setDirty(bool val = true, bool force_refresh = false); - uuid_vec_t& getIDs() { return mIDs; } + uuid_vec_t& getIDs() { return mIDs; } bool contains(const LLUUID& id); void setContextMenu(LLListContextMenu* menu) { mContextMenu = menu; } @@ -108,7 +109,8 @@ protected: const uuid_vec_t& vnew, uuid_vec_t& vadded, uuid_vec_t& vremoved); - void updateLastInteractionTimes(); + void updateLastInteractionTimes(); + void updateDistances(); void rebuildNames(); void onItemDoubleClicked(LLUICtrl* ctrl, S32 x, S32 y, MASK mask); void updateAvatarNames(); @@ -119,6 +121,7 @@ private: bool mIgnoreOnlineStatus; bool mShowLastInteractionTime; + bool mShowDistance; bool mDirty; bool mNeedUpdateNames; bool mShowIcons; diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index c43ff0f1776b06d6323af3fc11ddf940f768a245..1301361156ff6d2e7a4e7886ac0cbe5292a84e20 100755 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -66,6 +66,7 @@ LLAvatarListItem::LLAvatarListItem(bool not_from_ui_factory/* = true*/) LLFriendObserver(), mAvatarIcon(NULL), mAvatarName(NULL), + mDistance(nullptr), mLastInteractionTime(NULL), mIconPermissionOnline(NULL), mIconPermissionMap(NULL), @@ -108,6 +109,7 @@ BOOL LLAvatarListItem::postBuild() { mAvatarIcon = getChild<LLAvatarIconCtrl>("avatar_icon"); mAvatarName = getChild<LLTextBox>("avatar_name"); + mDistance = getChild<LLTextBox>("distance"); mLastInteractionTime = getChild<LLTextBox>("last_interaction"); mIconPermissionOnline = getChild<LLIconCtrl>("permission_online_icon"); @@ -305,6 +307,20 @@ void LLAvatarListItem::setAvatarId(const LLUUID& id, const LLUUID& session_id, b } } +void LLAvatarListItem::showDistance(bool show) +{ + mDistance->setVisible(show); + updateChildren(); +} + +void LLAvatarListItem::setDistance(F32 distance) +{ + if (distance == 0) + mDistance->setValue(LLStringUtil::null); + else + mDistance->setValue(llformat("%0.1fm", distance)); +} + void LLAvatarListItem::showLastInteractionTime(bool show) { mLastInteractionTime->setVisible(show); @@ -550,6 +566,8 @@ void LLAvatarListItem::initChildrenWidths(LLAvatarListItem* avatar_item) // last interaction time textbox width + padding S32 last_interaction_time_width = avatar_item->mIconPermissionOnlineTheirs->getRect().mLeft - avatar_item->mLastInteractionTime->getRect().mLeft; + + S32 distance_width = avatar_item->mIconPermissionOnlineTheirs->getRect().mLeft - avatar_item->mDistance->getRect().mLeft; // avatar icon width + padding S32 icon_width = avatar_item->mAvatarName->getRect().mLeft - avatar_item->mAvatarIcon->getRect().mLeft; @@ -559,6 +577,7 @@ void LLAvatarListItem::initChildrenWidths(LLAvatarListItem* avatar_item) S32 index = ALIC_COUNT; 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] = distance_width; sChildrenWidths[--index] = last_interaction_time_width; sChildrenWidths[--index] = permission_online_theirs_width; sChildrenWidths[--index] = permission_map_theirs_width; @@ -685,6 +704,9 @@ LLView* LLAvatarListItem::getItemChildView(EAvatarListItemChildIndex child_view_ case ALIC_NAME: child_view = mAvatarName; break; + case ALIC_DISTANCE: + child_view = mDistance; + break; case ALIC_INTERACTION_TIME: child_view = mLastInteractionTime; break; diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h index 6519d3c15b328e12094481df0ca8751a37f6ad0f..3b845ebe6e46ab4472c61475b4ec6ab6fc102198 100755 --- a/indra/newview/llavatarlistitem.h +++ b/indra/newview/llavatarlistitem.h @@ -99,11 +99,13 @@ public: void setState(EItemState item_style); void setAvatarId(const LLUUID& id, const LLUUID& session_id, bool ignore_status_changes = false, bool is_resident = true); void setLastInteractionTime(U32 secs_since); + void setDistance(F32 distance); //Show/hide profile/info btn, translating speaker indicator and avatar name coordinates accordingly void setShowProfileBtn(bool show); void setShowInfoBtn(bool show); void showSpeakingIndicator(bool show); void setShowPermissions(bool show) { mShowPermissions = show; }; + void showDistance(bool show); void showLastInteractionTime(bool show); void setAvatarIconVisible(bool visible); @@ -165,6 +167,7 @@ private: ALIC_PERMISSION_MAP_THEIRS, ALIC_PERMISSION_ONLINE_THEIRS, ALIC_INTERACTION_TIME, + ALIC_DISTANCE, ALIC_NAME, ALIC_ICON, ALIC_COUNT, @@ -206,6 +209,7 @@ private: LLView* getItemChildView(EAvatarListItemChildIndex child_index); LLTextBox* mAvatarName; + LLTextBox* mDistance; LLTextBox* mLastInteractionTime; LLStyle::Params mAvatarNameStyle; diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index aa7b76da0936a943ef4b82febee3da8cb17b6deb..51d23351e92ecfcd26d9186ec01e16e822daee1b 100755 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -1334,6 +1334,56 @@ void LLWorld::getAvatars(uuid_vec_t* avatar_ids, std::vector<LLVector3d>* positi } } +void LLWorld::getAvatars(boost::unordered_map<LLUUID, LLVector3d>* umap, const LLVector3d& relative_to, F32 radius) const +{ + F32 radius_squared = radius * radius; + + if (!umap->empty()) + { + umap->clear(); + } + // get the list of avatars from the character list first, so distances are correct + // when agent is above 1020m and other avatars are nearby + for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) + { + LLVOAvatar* pVOAvatar = (LLVOAvatar*) *iter; + + if (!pVOAvatar->isDead() && !pVOAvatar->mIsDummy) + { + LLVector3d pos_global = pVOAvatar->getPositionGlobal(); + LLUUID uuid = pVOAvatar->getID(); + + if (!uuid.isNull() + && dist_vec_squared(pos_global, relative_to) <= radius_squared) + { + umap->emplace(uuid, pos_global); + } + } + } + // region avatars added for situations where radius is greater than RenderFarClip + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* regionp = *iter; + const LLVector3d& origin_global = regionp->getOriginGlobal(); + S32 count = regionp->mMapAvatars.size(); + for (S32 i = 0; i < count; i++) + { + LLVector3d pos_global = unpackLocalToGlobalPosition(regionp->mMapAvatars.at(i), origin_global); + if(dist_vec_squared(pos_global, relative_to) <= radius_squared) + { + LLUUID uuid = regionp->mMapAvatarIDs.at(i); + // if this avatar doesn't already exist in the list, add it + if(uuid.notNull()) + { + umap->emplace(uuid, pos_global); + } + } + } + } +} + bool LLWorld::isRegionListed(const LLViewerRegion* region) const { region_list_t::const_iterator it = find(mRegionList.begin(), mRegionList.end(), region); diff --git a/indra/newview/llworld.h b/indra/newview/llworld.h index b2d84180648ddfadc41c3ce0185f9354153451d8..af20e280bfe9b44621821d6c6e5e018c825d1b2c 100755 --- a/indra/newview/llworld.h +++ b/indra/newview/llworld.h @@ -162,6 +162,10 @@ public: uuid_vec_t* avatar_ids = NULL, std::vector<LLVector3d>* positions = NULL, const LLVector3d& relative_to = LLVector3d(), F32 radius = FLT_MAX) const; + + void getAvatars(boost::unordered_map<LLUUID, LLVector3d>* map = NULL, + const LLVector3d& relative_to = LLVector3d(), + F32 radius = FLT_MAX) const; // Returns 'true' if the region is in mRegionList, // 'false' if the region has been removed due to region change 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 c1bea89aeee63285cb64431c2f8c33836833ddf6..1c2ca9f0b91be9f1853106e500ba429abdc5bda5 100755 --- 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,6 +65,17 @@ use_ellipses="true" value="(loading)" width="180" /> + <text + follows="right" + font="SansSerifSmall" + height="15" + layout="topleft" + left_pad="5" + right="-168" + name="distance" + text_color="LtGray_50" + value="" + width="60" /> <text follows="right" font="SansSerifSmall" diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index fe82741af9a5636c72e92ac5de0b37825a1a6839..5e9098c07afcf4c7a74b0850b71dad4b63d8698d 100755 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -203,6 +203,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M right="-1" user_resize="true"> <avatar_list + show_distance="true" allow_select="true" follows="all" height="211"