From c5926546aa73bfb2900dda7d010a4d72550e6787 Mon Sep 17 00:00:00 2001 From: McCabe Maxsted Date: Tue, 11 Aug 2009 17:47:40 -0700 Subject: Moved radar back into llfloatermap.cpp, it works --- linden/indra/newview/llfloatermap.cpp | 256 +++++++++++++++++++++ linden/indra/newview/llfloatermap.h | 21 +- linden/indra/newview/llnetmap.cpp | 177 +------------- linden/indra/newview/llnetmap.h | 12 - linden/indra/newview/skins/default/colors_base.xml | 1 + .../skins/default/xui/en-us/floater_mini_map.xml | 47 ++-- 6 files changed, 316 insertions(+), 198 deletions(-) (limited to 'linden') diff --git a/linden/indra/newview/llfloatermap.cpp b/linden/indra/newview/llfloatermap.cpp index 6115404..b420eca 100644 --- a/linden/indra/newview/llfloatermap.cpp +++ b/linden/indra/newview/llfloatermap.cpp @@ -42,6 +42,20 @@ #include "llresizebar.h" #include "lluictrlfactory.h" +// radar +#include "llfloateravatarinfo.h" +#include "llfloaterfriends.h" +#include "llfloatergroupinvite.h" +#include "llfloatergroups.h" +#include "llimview.h" +#include "roles_constants.h" +#include "llscrolllistctrl.h" +#include "lltracker.h" +#include "llviewermessage.h" +#include "llworld.h" + +LLFloaterMap* LLFloaterMap::sInstance = NULL; + LLFloaterMap::LLFloaterMap(const LLSD& key) : LLFloater(std::string("minimap")), @@ -50,6 +64,7 @@ LLFloaterMap::LLFloaterMap(const LLSD& key) LLCallbackMap::map_t factory_map; factory_map["mini_mapview"] = LLCallbackMap(createPanelMiniMap, this); LLUICtrlFactory::getInstance()->buildFloater(this, "floater_mini_map.xml", &factory_map, FALSE); + sInstance = this; } @@ -58,6 +73,7 @@ void* LLFloaterMap::createPanelMiniMap(void* data) { LLFloaterMap* self = (LLFloaterMap*)data; self->mPanelMap = new LLNetMap("Mapview"); + self->mSelectedAvatar.setNull(); return self->mPanelMap; } @@ -67,12 +83,28 @@ BOOL LLFloaterMap::postBuild() sendChildToBack(getDragHandle()); sendChildToFront(getChild<LLButton>("llfloater_close_btn")); setIsChrome(TRUE); + + mRadarList = getChild<LLScrollListCtrl>("RadarList"); + childSetCommitCallback("RadarList", onList, this); + + childSetAction("im_btn", onClickIM, this); + childSetAction("profile_btn", onClickProfile, this); + childSetAction("offer_teleport_btn", onClickOfferTeleport, this); + childSetAction("track_btn", onClickTrack, this); + childSetAction("invite_btn", onClickInvite, this); + childSetAction("add_btn", onClickAddFriend, this); + + setDefaultBtn("im_btn"); + + populateRadar(); + return TRUE; } LLFloaterMap::~LLFloaterMap() { + sInstance = NULL; } @@ -122,3 +154,227 @@ void LLFloaterMap::draw() } } + +// +// Radar +// + +//static +void LLFloaterMap::updateRadar() +{ + LLFloaterMap* self = sInstance; + self->populateRadar(); +} + +void LLFloaterMap::populateRadar() +{ + BOOL empty = TRUE; + std::stringstream avatar_count_string; + LLScrollListCtrl* radar_scroller = getChild<LLScrollListCtrl>("RadarList"); + radar_scroller->deleteAllItems(); + + LLVector3d current_pos = gAgent.getPositionGlobal(); + + std::vector<LLUUID> avatar_ids; + std::vector<LLVector3d> positions; + LLWorld::getInstance()->getAvatars(&avatar_ids, &positions, current_pos, gSavedSettings.getF32("NearMeRange")); + for(U32 i=0; i<avatar_ids.size(); i++) + { + LLUUID& av = avatar_ids[i]; + + if(av == gAgent.getID()) + continue; + + LLVector3d avatar_pos = positions[i]; + F64 distance = dist_vec(current_pos, avatar_pos); + std::stringstream dist_formatted; + dist_formatted << (double)((int)((distance + 0.05)*10.0))/10.0 << "m"; + + LLSD element; + element["id"] = av; // value + element["columns"][0]["column"] = "avatar_name"; + element["columns"][0]["type"] = "text"; + + std::string fullname; + if(!gCacheName->getFullName(av, fullname)) + { + element["columns"][0]["value"] = LLCacheName::getDefaultName(); + } + else + { + element["columns"][0]["value"] = fullname; + } + + element["columns"][1]["column"] = "avatar_distance"; + element["columns"][1]["type"] = "text"; + element["columns"][1]["value"] = dist_formatted.str(); + radar_scroller->addElement(element); + empty = FALSE; + } + + avatar_count_string.str(""); + if (empty) + { + childSetEnabled("RadarList", false);childSetEnabled("im_btn", false); + radar_scroller->addCommentText(getString("no_one_near")); + avatar_count_string << "0"; + } + else + { + childSetEnabled("RadarList", true); + radar_scroller->selectFirstItem(); + avatar_count_string << (int)avatar_ids.size(); + } + LLTextBox* lblAvatarCount = getChild<LLTextBox>("lblAvatarCount"); + lblAvatarCount->setText(avatar_count_string.str()); + + onList(radar_scroller, this); +} + +// static +void LLFloaterMap::onList(LLUICtrl* ctrl, void* user_data) +{ + LLFloaterMap* self = (LLFloaterMap*)user_data; + if (self) + { + self->childSetEnabled("im_btn", self->visibleItemsSelected()); + self->childSetEnabled("profile_btn", self->visibleItemsSelected()); + self->childSetEnabled("offer_teleport_btn", self->visibleItemsSelected()); + self->childSetEnabled("track_btn", self->visibleItemsSelected()); + self->childSetEnabled("invite_btn", self->visibleItemsSelected()); + self->childSetEnabled("add_btn", self->visibleItemsSelected()); + + if (self->visibleItemsSelected()) + { + self->mSelectedAvatar = self->mRadarList->getFirstSelected()->getUUID(); + } + else + { + self->mSelectedAvatar.setNull(); + } + } +} + +BOOL LLFloaterMap::visibleItemsSelected() const +{ + if (mRadarList->getFirstSelectedIndex() >= 0) + { + return TRUE; + } + return FALSE; +} + +// static +BOOL LLFloaterMap::isSelected(LLUUID agent) +{ + if (sInstance->mSelectedAvatar == agent) + { + return TRUE; + } + return FALSE; +} + +// static +void LLFloaterMap::onClickIM(void* user_data) +{ + LLFloaterMap* self = (LLFloaterMap*) user_data; + LLScrollListItem *item = self->mRadarList->getFirstSelected(); + if (item != NULL) + { + LLUUID agent_id = item->getUUID(); + std::string fullname; + if(gCacheName->getFullName(agent_id, fullname)) + { + gIMMgr->setFloaterOpen(TRUE); + gIMMgr->addSession(fullname, IM_NOTHING_SPECIAL, agent_id); + } + } +} + +// static +void LLFloaterMap::onClickProfile(void* user_data) +{ + LLFloaterMap* self = (LLFloaterMap*) user_data; + LLScrollListItem *item = self->mRadarList->getFirstSelected(); + if (item != NULL) + { + LLUUID agent_id = item->getUUID(); + LLFloaterAvatarInfo::show(agent_id); + } +} + +// static +void LLFloaterMap::onClickOfferTeleport(void* user_data) +{ + LLFloaterMap* self = (LLFloaterMap*) user_data; + LLScrollListItem *item = self->mRadarList->getFirstSelected(); + if (item != NULL) + { + LLUUID agent_id = item->getUUID(); + handle_lure(agent_id); + } +} + +// static +void LLFloaterMap::onClickTrack(void* user_data) +{ + LLFloaterMap* self = (LLFloaterMap*) user_data; + LLTracker::ETrackingStatus tracking_status = LLTracker::getTrackingStatus(); + if (LLTracker::TRACKING_AVATAR == tracking_status) + { + LLTracker::stopTracking(NULL); + } + else + { + LLScrollListItem *item = self->mRadarList->getFirstSelected(); + if (item != NULL) + { + LLUUID agent_id = item->getUUID(); + std::string fullname; + gCacheName->getFullName(agent_id, fullname); + LLTracker::trackAvatar(agent_id, fullname); + } + } +} + +// static +void LLFloaterMap::onClickInvite(void* user_data) +{ + LLFloaterMap* self = (LLFloaterMap*) user_data; + LLScrollListItem *item = self->mRadarList->getFirstSelected(); + if (item != NULL) + { + LLUUID agent_id = item->getUUID(); + LLFloaterGroupPicker* widget; + widget = LLFloaterGroupPicker::showInstance(LLSD(gAgent.getID())); + if (widget) + { + widget->center(); + widget->setPowersMask(GP_MEMBER_INVITE); + widget->setSelectCallback(callback_invite_to_group, (void *)&agent_id); + } + } +} + +// static +void LLFloaterMap::callback_invite_to_group(LLUUID group_id, void *user_data) +{ + std::vector<LLUUID> agent_ids; + agent_ids.push_back(*(LLUUID *)user_data); + + LLFloaterGroupInvite::showForGroup(group_id, &agent_ids); +} + +// static +void LLFloaterMap::onClickAddFriend(void* user_data) +{ + LLFloaterMap* self = (LLFloaterMap*) user_data; + LLScrollListItem *item = self->mRadarList->getFirstSelected(); + if (item != NULL) + { + LLUUID agent_id = item->getUUID(); + std::string fullname; + gCacheName->getFullName(agent_id, fullname); + LLPanelFriends::requestFriendshipDialog(agent_id, fullname); + } +} diff --git a/linden/indra/newview/llfloatermap.h b/linden/indra/newview/llfloatermap.h index dd1cba8..e099b4e 100644 --- a/linden/indra/newview/llfloatermap.h +++ b/linden/indra/newview/llfloatermap.h @@ -33,6 +33,7 @@ #define LL_LLFLOATERMAP_H #include "llfloater.h" +#include "llscrolllistctrl.h" class LLNetMap; @@ -46,6 +47,9 @@ public: static void* createPanelMiniMap(void* data); + static void updateRadar(); + static BOOL isSelected(LLUUID agent); + BOOL postBuild(); /*virtual*/ void draw(); @@ -55,7 +59,22 @@ public: private: LLFloaterMap(const LLSD& key = LLSD()); - LLNetMap* mPanelMap; + LLNetMap* mPanelMap; + LLScrollListCtrl* mRadarList; + LLUUID mSelectedAvatar; + static LLFloaterMap* sInstance; + + static void onList(class LLUICtrl* ctrl, void* user_data); + BOOL visibleItemsSelected() const; + void populateRadar(); + + static void onClickProfile(void* user_data); + static void onClickIM(void* user_data); + static void onClickAddFriend(void* user_data); + static void onClickOfferTeleport(void* user_data); + static void onClickTrack(void* user_data); + static void onClickInvite(void* user_data); + static void callback_invite_to_group(LLUUID group_id, void *user_data); }; #endif // LL_LLFLOATERMAP_H diff --git a/linden/indra/newview/llnetmap.cpp b/linden/indra/newview/llnetmap.cpp index 903f6f3..2429aa4 100644 --- a/linden/indra/newview/llnetmap.cpp +++ b/linden/indra/newview/llnetmap.cpp @@ -44,6 +44,8 @@ #include "llcallingcard.h" #include "llcolorscheme.h" #include "llviewercontrol.h" +#include "llfloateravatarinfo.h" +#include "llfloatermap.h" #include "llfloaterworldmap.h" #include "llframetimer.h" #include "llmutelist.h" @@ -65,14 +67,6 @@ #include "llworldmapview.h" // shared draw code #include "llappviewer.h" // Only for constants! -// radar -#include "llfloateravatarinfo.h" -#include "llfloatergroupinvite.h" -#include "llfloatergroups.h" -#include "roles_constants.h" -#include "llimview.h" -#include "llscrolllistctrl.h" - #include "llglheaders.h" const F32 MAP_SCALE_MIN = 32; @@ -112,8 +106,6 @@ LLNetMap::LLNetMap(const std::string& name) : (new LLEnableProfile())->registerListener(this, "MiniMap.EnableProfile"); LLUICtrlFactory::getInstance()->buildPanel(this, "panel_mini_map.xml"); - //TODO: This'll make it toggle - //LLUICtrlFactory::getInstance()->buildPanel(this, "panel_mini_map_radar.xml"); updateMinorDirections(); @@ -128,17 +120,6 @@ LLNetMap::LLNetMap(const std::string& name) : BOOL LLNetMap::postBuild() { - mRadarList = getChild<LLScrollListCtrl>("RadarList"); - - childSetAction("im_btn", onClickIM, this); - childSetAction("profile_btn", onClickProfile, this); - childSetAction("offer_teleport_btn", onClickOfferTeleport, this); - childSetAction("track_btn", onClickTrack, this); - childSetAction("invite_btn", onClickInvite, this); - childSetAction("add_btn", onClickAddFriend, this); - - setDefaultBtn("im_btn"); - return TRUE; } @@ -355,6 +336,7 @@ void LLNetMap::draw() LLColor4 avatar_color = gColors.getColor( "MapAvatar" ); LLColor4 friend_color = gColors.getColor( "MapFriend" ); LLColor4 muted_color = gColors.getColor( "MapMuted" ); + LLColor4 selected_color = gColors.getColor( "MapSelected" ); LLColor4 glyph_color; std::vector<LLUUID> avatar_ids; @@ -375,6 +357,10 @@ void LLNetMap::draw() { glyph_color = friend_color; } + else if (LLFloaterMap::isSelected(avatar_ids[i])) + { + glyph_color = selected_color; + } else { glyph_color = avatar_color; @@ -474,9 +460,9 @@ void LLNetMap::draw() setDirectionPos( getChild<LLTextBox>("sw_label"), rotation + F_PI + F_PI_BY_TWO / 2); setDirectionPos( getChild<LLTextBox>("se_label"), rotation + F_PI + F_PI_BY_TWO + F_PI_BY_TWO / 2); - populateRadar(); - LLView::draw(); + + LLFloaterMap::updateRadar(); } void LLNetMap::reshape(S32 width, S32 height, BOOL called_from_parent) @@ -975,148 +961,3 @@ bool LLNetMap::LLEnableProfile::handleEvent(LLPointer<LLEvent> event, const LLSD self->findControl(userdata["control"].asString())->setValue(self->isAgentUnderCursor()); return true; } - - -// -// Radar -// - -void LLNetMap::populateRadar() -{ - BOOL all_loaded = TRUE; - BOOL empty = TRUE; - LLScrollListCtrl* radar_scroller = getChild<LLScrollListCtrl>("RadarList"); - radar_scroller->deleteAllItems(); - - std::vector<LLUUID> avatar_ids; - LLWorld::getInstance()->getAvatars(&avatar_ids, NULL, gAgent.getPositionGlobal(), gSavedSettings.getF32("NearMeRange")); - for(U32 i=0; i<avatar_ids.size(); i++) - { - LLUUID& av = avatar_ids[i]; - if(av == gAgent.getID()) continue; - LLSD element; - element["id"] = av; // value - std::string fullname; - if(!gCacheName->getFullName(av, fullname)) - { - element["columns"][0]["value"] = LLCacheName::getDefaultName(); - all_loaded = FALSE; - } - else - { - element["columns"][0]["value"] = fullname; - } - radar_scroller->addElement(element); - empty = FALSE; - } - - if (empty) - { - childDisable("RadarList"); - //radar_scroller->addCommentText(getString("no_one_near")); - } - else - { - childEnable("RadarList"); - radar_scroller->selectFirstItem(); - //onList(radar_scroller, this); - radar_scroller->setFocus(TRUE); - } - - //if (all_loaded) - //{ - // mRadarListComplete = TRUE; - //} -} - -// TODO: Since there're no tabs, move this up above -//void LLNetMap::onList(LLUICtrl* ctrl, void* userdata) -//{ -// LLNetMap* self = (LLNetMap*)userdata; -// if (self) -// { -// self->childSetEnabled("im_btn", self->visibleItemsSelected()); -// self->childSetEnabled("profile_btn", self->visibleItemsSelected()); -// self->childSetEnabled("offer_teleport_btn", self->visibleItemsSelected()); -// self->childSetEnabled("track_btn", self->visibleItemsSelected()); -// self->childSetEnabled("invite_btn", self->visibleItemsSelected()); -// self->childSetEnabled("add_btn", self->visibleItemsSelected()); -// } -//} - -void LLNetMap::onClickIM(void* user_data) -{ - LLNetMap* self = (LLNetMap*) user_data; - - LLScrollListItem *item = self->mRadarList->getFirstSelected(); - LLUUID agent_id = item->getUUID(); - std::string fullname; - if(gCacheName->getFullName(agent_id, fullname)) - { - gIMMgr->setFloaterOpen(TRUE); - gIMMgr->addSession(fullname, IM_NOTHING_SPECIAL, agent_id); - } -} - -void LLNetMap::onClickProfile(void* user_data) -{ - LLNetMap* self = (LLNetMap*) user_data; - - LLScrollListItem *item = self->mRadarList->getFirstSelected(); - LLUUID agent_id = item->getUUID(); - LLFloaterAvatarInfo::show(agent_id); -} - -void LLNetMap::onClickOfferTeleport(void* user_data) -{ -} - -void LLNetMap::onClickTrack(void* user_data) -{ - LLNetMap* self = (LLNetMap*) user_data; - - LLTracker::ETrackingStatus tracking_status = LLTracker::getTrackingStatus(); - if (LLTracker::TRACKING_AVATAR == tracking_status) - { - LLTracker::stopTracking(NULL); - } - else - { - LLScrollListItem *item = self->mRadarList->getFirstSelected(); - LLUUID agent_id = item->getUUID(); - std::string fullname; - gCacheName->getFullName(agent_id, fullname); - LLTracker::trackAvatar(agent_id, fullname); - } -} - -void LLNetMap::onClickInvite(void* user_data) -{ - LLNetMap* self = (LLNetMap*) user_data; - - LLScrollListItem *item = self->mRadarList->getFirstSelected(); - LLUUID agent_id = item->getUUID(); - { - LLFloaterGroupPicker* widget; - widget = LLFloaterGroupPicker::showInstance(LLSD(gAgent.getID())); - if (widget) - { - widget->center(); - widget->setPowersMask(GP_MEMBER_INVITE); - widget->setSelectCallback(callback_invite_to_group, (void *)&agent_id); - } - } -} - -void LLNetMap::callback_invite_to_group(LLUUID group_id, void *user_data) -{ - std::vector<LLUUID> agent_ids; - agent_ids.push_back(*(LLUUID *)user_data); - - LLFloaterGroupInvite::showForGroup(group_id, &agent_ids); -} - -void LLNetMap::onClickAddFriend(void* user_data) -{ -} - diff --git a/linden/indra/newview/llnetmap.h b/linden/indra/newview/llnetmap.h index 58b2066..45b5e2d 100644 --- a/linden/indra/newview/llnetmap.h +++ b/linden/indra/newview/llnetmap.h @@ -34,7 +34,6 @@ #include "llpanel.h" #include "llmemberlistener.h" -#include "llscrolllistctrl.h" #include "v3math.h" #include "v3dmath.h" #include "v4color.h" @@ -116,7 +115,6 @@ private: private: LLUUID mClosestAgentToCursor; LLUUID mClosestAgentAtLastRightClick; - LLScrollListCtrl* mRadarList; static BOOL sRotateMap; static LLNetMap* sInstance; @@ -126,16 +124,6 @@ private: static void showAgentProfile(void*); BOOL isAgentUnderCursor() { return mClosestAgentToCursor.notNull(); } - void populateRadar(); - - static void onClickProfile(void* user_data); - static void onClickIM(void* user_data); - static void onClickAddFriend(void* user_data); - static void onClickOfferTeleport(void* user_data); - static void onClickTrack(void* user_data); - static void onClickInvite(void* user_data); - static void callback_invite_to_group(LLUUID group_id, void *user_data); - class LLScaleMap : public LLMemberListener<LLNetMap> { public: diff --git a/linden/indra/newview/skins/default/colors_base.xml b/linden/indra/newview/skins/default/colors_base.xml index 42cb0ac..38499d3 100644 --- a/linden/indra/newview/skins/default/colors_base.xml +++ b/linden/indra/newview/skins/default/colors_base.xml @@ -160,6 +160,7 @@ <MapAvatar value="0, 255, 0, 255" /> <!-- Your avatar's glyph color --> <MapFriend value="255, 255, 0, 255" /> <!-- Your friends' glyph color --> <MapMuted value="128, 128, 128, 255" /> <!-- Muted avatars' glyph color --> +<MapSelected value="255, 0, 0, 255" /> <!-- Selected avatars' glyph color --> <!-- MINI-MAP --> <NetMapBackgroundColor value="0, 0, 0, 77" /> <!-- Mini-map floater background --> diff --git a/linden/indra/newview/skins/default/xui/en-us/floater_mini_map.xml b/linden/indra/newview/skins/default/xui/en-us/floater_mini_map.xml index c10367d..3408c76 100644 --- a/linden/indra/newview/skins/default/xui/en-us/floater_mini_map.xml +++ b/linden/indra/newview/skins/default/xui/en-us/floater_mini_map.xml @@ -10,31 +10,41 @@ <panel name="RadarPanel" label="Radar" background_visible="true" bg_alpha_color="NetMapBackgroundColor" left="2" top="196" right="196" height="120" - follows="left|right|bottom" border="true" mouse_opaque="true"> + follows="left|right|bottom" border="false" mouse_opaque="true"> <text bg_visible="false" border_drop_shadow_visible="false" border_visible="false" - bottom="-20" drop_shadow_visible="true" follows="left|top" - font="SansSerifSmall" h_pad="0" halign="left" height="16" left="10" - mouse_opaque="true" name="InstructSelectResident" v_pad="0" - width="220"> - Select nearby resident: + bottom="-20" drop_shadow_visible="true" follows="left|top" + font="SansSerifSmall" h_pad="0" halign="left" height="16" left="10" + mouse_opaque="true" name="lblAvatarCount" v_pad="0" + width="220"> + 0 </text> - <slider bottom_delta="-20" left="10" follows="left|top" width="175" height="15" - name="near_me_range" label="Range" control_name="NearMeRange" + <text bg_visible="false" border_drop_shadow_visible="false" border_visible="false" + bottom="-20" drop_shadow_visible="true" follows="left|top" + font="SansSerifSmall" h_pad="0" halign="left" height="16" left="27" + mouse_opaque="true" name="avatars_in" v_pad="0" + width="220"> + Avatars in + </text> + <slider bottom_delta="0" left_delta="55" follows="left|top" width="110" height="15" + name="near_me_range" label="" control_name="NearMeRange" min_val="5" max_val="256" increment="1" initial_val="96" decimal_digits="0" /> <text bg_visible="false" border_drop_shadow_visible="false" border_visible="false" - bottom_delta="0" left="185" drop_shadow_visible="true" follows="left|top" + bottom_delta="0" left="190" drop_shadow_visible="true" follows="left|top" font="SansSerifSmall" h_pad="0" halign="left" height="15" mouse_opaque="true" name="meters" v_pad="0" width="40"> Meters </text> - <scroll_list bottom_delta="-100" width="96" height="100" left="10" - follows="left|top|bottom|right" draw_border="true" draw_heading="false" - draw_stripes="true" column_padding="5" sort_column="0" mouse_opaque="true" - background_visible="true" multi_select="false" name="RadarList" /> - <button bottom_delta="100" follows="top|right" height="22" label="IM/Call" - left="-90" name="im_btn" tool_tip="Open Instant Message session" + <scroll_list bottom_delta="-166" width="96" height="160" left="10" + follows="left|top|bottom|right" draw_border="false" draw_heading="true" + draw_stripes="true" column_padding="5" sort_column="1" mouse_opaque="true" + background_visible="true" multi_select="false" name="RadarList"> + <column name="avatar_name" label="Name" dynamicwidth="true" /> + <column name="avatar_distance" label="Dist." width="55" /> + </scroll_list> + <button bottom="-45" follows="top|right" height="22" label="IM/Call" + left="-85" name="im_btn" tool_tip="Open Instant Message session" width="80" /> <button bottom_delta="-25" follows="top|right" height="22" label="Profile" left_delta="0" name="profile_btn" @@ -45,11 +55,14 @@ <button bottom_delta="-25" follows="top|right" height="22" label="Track" left_delta="0" name="track_btn" tool_tip="Create a beacon to track this avatar" width="80" /> - <button bottom_delta="-35" follows="top|right" height="22" label="Invite..." + <button bottom_delta="-30" follows="top|right" height="22" label="Invite..." left_delta="0" name="invite_btn" tool_tip="Remove this person from your friends list" width="80" /> - <button bottom_delta="-35" follows="top|right" height="22" label="Add..." + <button bottom_delta="-30" follows="top|right" height="22" label="Add..." left_delta="0" name="add_btn" tool_tip="Offer friendship to a resident" width="80" /> + <string name="no_one_near"> + No avatars within range + </string> </panel> </floater> -- cgit v1.1