From fa004431e6dc454f1ceacace1234c39bb19f7d89 Mon Sep 17 00:00:00 2001 From: McCabe Maxsted Date: Sat, 5 Jun 2010 02:19:12 -0700 Subject: Rewrote the radar code to fix some basic issues i.e. avatars stuck as typing, appearing multiple times, or spamming the chat notify (also added a ban button while I was there) --- linden/indra/newview/CMakeLists.txt | 2 + linden/indra/newview/app_settings/settings.xml | 11 + linden/indra/newview/llnetmap.cpp | 4 +- linden/indra/newview/llviewermessage.cpp | 13 +- linden/indra/newview/panelradar.cpp | 672 ++++++++++++--------- linden/indra/newview/panelradar.h | 64 +- linden/indra/newview/panelradarentry.cpp | 85 +++ linden/indra/newview/panelradarentry.h | 83 +++ .../skins/default/xui/en-us/panel_radar.xml | 32 +- 9 files changed, 627 insertions(+), 339 deletions(-) create mode 100644 linden/indra/newview/panelradarentry.cpp create mode 100644 linden/indra/newview/panelradarentry.h (limited to 'linden') diff --git a/linden/indra/newview/CMakeLists.txt b/linden/indra/newview/CMakeLists.txt index 70d4257..6be53a4 100644 --- a/linden/indra/newview/CMakeLists.txt +++ b/linden/indra/newview/CMakeLists.txt @@ -461,6 +461,7 @@ set(viewer_SOURCE_FILES llxmlrpctransaction.cpp noise.cpp panelradar.cpp + panelradarentry.cpp pipeline.cpp primbackup.cpp rlvhandler.cpp @@ -894,6 +895,7 @@ set(viewer_HEADER_FILES macmain.h noise.h panelradar.h + panelradarentry.h pipeline.h primbackup.h randgauss.h diff --git a/linden/indra/newview/app_settings/settings.xml b/linden/indra/newview/app_settings/settings.xml index 89cf2ab..85665cf 100644 --- a/linden/indra/newview/app_settings/settings.xml +++ b/linden/indra/newview/app_settings/settings.xml @@ -48,6 +48,17 @@ Value + ChatDistance + + Comment + Default chat distance in meters + Persist + 1 + Type + U32 + Value + 20 + CmdLineCacheLocation Comment diff --git a/linden/indra/newview/llnetmap.cpp b/linden/indra/newview/llnetmap.cpp index 6ebf98e..d587170 100644 --- a/linden/indra/newview/llnetmap.cpp +++ b/linden/indra/newview/llnetmap.cpp @@ -372,7 +372,7 @@ void LLNetMap::draw() { glyph_color = muted_color; } - else if (PanelRadar::isImpDev(avatar_ids[i])) + else if (LLFloaterMap::getInstance()->getRadar()->isImpDev(avatar_ids[i])) { glyph_color = imp_dev_color; } @@ -516,7 +516,7 @@ void LLNetMap::draw() LLView::draw(); - LLFloaterMap::getInstance()->getRadar()->populateRadar(); + LLFloaterMap::getInstance()->getRadar()->updateRadarInfo(); } void LLNetMap::reshape(S32 width, S32 height, BOOL called_from_parent) diff --git a/linden/indra/newview/llviewermessage.cpp b/linden/indra/newview/llviewermessage.cpp index 35fd669..76c1508 100644 --- a/linden/indra/newview/llviewermessage.cpp +++ b/linden/indra/newview/llviewermessage.cpp @@ -140,6 +140,7 @@ #include "llwlparammanager.h" #include "llwaterparammanager.h" +#include "panelradarentry.h" #include #include // Boost Reg Expresions @@ -2785,7 +2786,11 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) if (LLFloaterMap::getInstance()) { - LLFloaterMap::getInstance()->getRadar()->addToTypingList(from_id); + PanelRadarEntry* entry = LLFloaterMap::getInstance()->getRadar()->getEntry(from_id); + if (entry) + { + entry->setStatus(RADAR_STATUS_TYPING); + } } return; @@ -2802,7 +2807,11 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) if (LLFloaterMap::getInstance()) { - LLFloaterMap::getInstance()->getRadar()->removeFromTypingList(from_id); + PanelRadarEntry* entry = LLFloaterMap::getInstance()->getRadar()->getEntry(from_id); + if (entry) + { + entry->setStatus(RADAR_STATUS_NONE); + } } return; diff --git a/linden/indra/newview/panelradar.cpp b/linden/indra/newview/panelradar.cpp index 5ad15c6..c4eec1f 100644 --- a/linden/indra/newview/panelradar.cpp +++ b/linden/indra/newview/panelradar.cpp @@ -36,6 +36,8 @@ #include "llfloaterfriends.h" #include "llfloatergroupinvite.h" #include "llfloatergroups.h" +#include "llfloatermap.h" +#include "llfloaterregioninfo.h" #include "llfloaterreporter.h" #include "llimview.h" #include "llmutelist.h" @@ -53,6 +55,7 @@ #include "llviewerwindow.h" #include "llvoavatar.h" #include "llworld.h" +#include "panelradarentry.h" PanelRadar::PanelRadar() @@ -61,10 +64,6 @@ PanelRadar::PanelRadar() mSelectedAvatar(LLUUID::null) { LLUICtrlFactory::getInstance()->buildPanel(this, "panel_radar.xml"); - - mChatAvatars.clear(); - mTypingAvatars.clear(); - mSimAvatars.clear(); } @@ -81,28 +80,27 @@ BOOL PanelRadar::postBuild() childSetAction("track_btn", onClickTrack, this); childSetAction("invite_btn", onClickInvite, this); childSetAction("add_btn", onClickAddFriend, this); + childSetAction("cam_btn", onClickCam, this); childSetAction("freeze_btn", onClickFreeze, this); childSetAction("eject_btn", onClickEject, this); childSetAction("mute_btn", onClickMute, this); childSetAction("unmute_btn", onClickUnmute, this); childSetAction("ar_btn", onClickAR, this); - childSetAction("estate_eject_btn", onClickEjectFromEstate, this); + //childSetAction("estate_eject_btn", onClickEjectFromEstate, this); + childSetAction("estate_ban_btn", onClickBanFromEstate, this); setDefaultBtn("im_btn"); - populateRadar(); + updateRadarInfo(); return TRUE; } - PanelRadar::~PanelRadar() { } - -//static -bool PanelRadar::isImpDev(LLUUID agent_id) +bool PanelRadar::isImpDev(const LLUUID& agent_id) { // We use strings here as avatar keys change across grids. // Feel free to add/remove yourself. @@ -112,300 +110,285 @@ bool PanelRadar::isImpDev(LLUUID agent_id) agent_name == "Armin Weatherwax"); } - -void PanelRadar::populateRadar() +void PanelRadar::updateRadarInfo() { if (!getVisible()) { return; } - if (visibleItemsSelected()) - { - mSelectedAvatar = mRadarList->getFirstSelected()->getUUID(); - } - else - { - mSelectedAvatar.setNull(); - } - - S32 scroll_pos = mRadarList->getScrollPos(); - - // clear count - std::stringstream avatar_count; - avatar_count.str(""); - - // find what avatars you can see - F32 range = gSavedSettings.getF32("NearMeRange"); - LLVector3d current_pos = gAgent.getPositionGlobal(); + // find what avatars we can know about std::vector avatar_ids; std::vector positions; LLWorld::getInstance()->getAvatars(&avatar_ids, &positions); - LLSD element; - - mRadarList->deleteAllItems(); - if (!avatar_ids.empty()) { for (U32 i=0; iisAvatar()) - { - LLVOAvatar* avatarp = (LLVOAvatar*)av_obj; - if (avatarp != NULL) - { - temp = avatarp->getPositionGlobal(); - } - } - } - F64 distance = dist_vec(temp, current_pos); - // we round for accuracy when avs tp in - std::string dist_string = llformat("%.1f", llround((F32)distance, 0.1f)); - - /*llinfos << "Avatar :" << fullname << " Position: " << positions[i] << " Your Position: " - << current_pos << " Distance: " << distance << llendl;*/ - - if (notify_chat) - { - if (distance < 20.0f) - { - if (!isInChatList(avatar_ids[i])) - { - addToChatList(avatar_ids[i], dist_string); - } - } - else - { - if (isInChatList(avatar_ids[i])) - { - removeFromChatList(avatar_ids[i]); - } - } - updateChatList(avatar_ids); - } - else if (!mChatAvatars.empty()) - { - mChatAvatars.clear(); - } - - if (notify_sim) + // If they aren't, create a new entry + // If they are, see if we need to update any values + // List them as "(Unknown)" if we can't get their name + if (!entry) + { + mAvatars.insert(std::pair(avatar_ids[i], PanelRadarEntry(avatar_ids[i], + getSelectedName(avatar_ids[i]), + calculateDistance(avatar_ids[i], positions[i]), + positions[i], + RADAR_STATUS_NONE, + RADAR_NOTIFIED_NONE) + )); + } + else + { + if (entry->getName() == getString("unknown_avatar")) { - if (!isInChatList(avatar_ids[i]) && !isInSimAvList(avatar_ids[i])) - { - LLViewerObject *av_obj = gObjectList.findObject(avatar_ids[i]); - if (av_obj != NULL && av_obj->isAvatar()) - { - LLVOAvatar* avatarp = (LLVOAvatar*)av_obj; - if (avatarp != NULL) - { - if (avatarp->getRegion() == gAgent.getRegion()) - { - addToSimAvList(avatar_ids[i], dist_string); - } - } - } - } - updateSimAvList(avatar_ids); + // Try to find the name again + entry->setName(getSelectedName(avatar_ids[i])); } - else if (!mSimAvatars.empty()) + if (entry->getPosition() != positions[i]) { - mSimAvatars.clear(); + entry->setPosition(positions[i]); } - - // only display avatars in range - if (distance <= range) + if (entry->getStatusTimer().hasExpired()) { - // append typing string - std::string typing = ""; - if (isTyping(avatar_ids[i])) - { - typing = getString("is_typing")+ " "; - } - - std::string mute_text = LLMuteList::getInstance()->isMuted(avatar_ids[i]) ? getString("is_muted") : ""; - element["id"] = avatar_ids[i]; - element["columns"][0]["column"] = "avatar_name"; - element["columns"][0]["type"] = "text"; - element["columns"][0]["value"] = typing + fullname + " " + mute_text; - element["columns"][1]["column"] = "avatar_distance"; - element["columns"][1]["type"] = "text"; - element["columns"][1]["value"] = dist_string+"m"; - - mRadarList->addElement(element, ADD_BOTTOM); + entry->setStatus(RADAR_STATUS_NONE); } + entry->setDistance(calculateDistance(avatar_ids[i], positions[i])); } } - - mRadarList->sortItems(); - mRadarList->setScrollPos(scroll_pos); - if (mSelectedAvatar.notNull()) - { - mRadarList->selectByID(mSelectedAvatar); - } - avatar_count << (int)avatar_ids.size(); - childSetText("avatars_in", ((int)avatar_ids.size() > 1) ? - getString("avatars_in_plural") : - getString("avatars_in_singular")); + removeDeadEntries(avatar_ids); } - else + else // avatar_ids empty { - mTypingAvatars.clear(); + mRadarList->deleteAllItems(); mRadarList->addCommentText(getString("no_one_near"), ADD_TOP); - avatar_count << "0"; - childSetText("avatars_in", getString("avatars_in_plural")); + LLUIString av_count_string = getString("avatars_in_plural"); + av_count_string.setArg("[COUNT]", "0"); + childSetText("avatar_count", av_count_string.getString()); + return; } - childSetText("lblAvatarCount", avatar_count.str()); - - updateButtonStates(); - - //llinfos << "mSelectedAvatar: " << mSelectedAvatar.asString() << llendl; + updateRadarDisplay(); } - -void PanelRadar::updateChatList(std::vector agent_ids) +void PanelRadar::updateRadarDisplay() { - std::set::iterator it; - std::vector::iterator result; - for (it = mChatAvatars.begin(); it != mChatAvatars.end(); ) + if (visibleItemsSelected()) { - result = find(agent_ids.begin(), agent_ids.end(), *it); - if (result == agent_ids.end()) - { - mChatAvatars.erase(it++); - } - else - { - it++; - } + mSelectedAvatar = mRadarList->getFirstSelected()->getUUID(); + } + else + { + mSelectedAvatar.setNull(); } -} + S32 scroll_pos = mRadarList->getScrollPos(); -bool PanelRadar::isInChatList(LLUUID agent_id) -{ - return (mChatAvatars.count(agent_id) > 0); -} + LLSD element; + // Zap all the avie names. Zap zap zap! + mRadarList->deleteAllItems(); -void PanelRadar::addToChatList(LLUUID agent_id, std::string distance) -{ - mChatAvatars.insert(agent_id); - LLChat chat; + U32 chat_distance = gSavedSettings.getU32("ChatDistance"); + F32 range = gSavedSettings.getF32("NearMeRange"); + bool notify_chat = gSavedSettings.getBOOL("MiniMapNotifyChatRange"); + bool notify_sim = gSavedSettings.getBOOL("MiniMapNotifySimRange"); +// [RLVa:KB] - Alternate: Imprudence-1.2.0 + if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) + { + notify_chat = false; + notify_sim = false; + } +// [/RLVa:KB] - LLUIString notify = getString("entering_chat_range"); - notify.setArg("[NAME]", getSelectedName(agent_id)); - notify.setArg("[DISTANCE]", distance); + std::map::iterator mIt; + for (mIt = mAvatars.begin(); mIt != mAvatars.end(); ++mIt) + { + PanelRadarEntry* entry = &mIt->second; + + LL_DEBUGS("Radar") << "Avatar :" << entry->getName() + << " Position: " << entry->getPosition() + << " Your Position: " << gAgent.getPositionGlobal() + << " Distance: " << entry->getDistance() + << " Status: " << entry->getStatus() + << " Notified: " << entry->getNotified() + << " Timer Seconds: " << entry->getStatusTimer().getElapsedTimeF32() + << LL_ENDL; + + // Check if they're in certain ranges and notify user if we've enabled that, starting with chat range + // We round for accuracy when avs tp in + std::string dist_string = llformat("%.1f", llround(entry->getDistance(), 0.1f)); + + // Don't notify if we don't know their name. It takes a few seconds for names to load on OpenSim, anyway + if (entry->getName() != getString("unknown_avatar")) + { + if (notify_sim && + (entry->getNotified() < RADAR_NOTIFIED_SIM)) + { + LLViewerObject *av_obj = gObjectList.findObject(entry->getID()); + if (av_obj != NULL && av_obj->isAvatar()) + { + LLVOAvatar* avatarp = (LLVOAvatar*)av_obj; + if (avatarp != NULL) + { + if (avatarp->getRegion() == gAgent.getRegion()) + { + LLChat chat; + LLUIString notify = getString("entering_sim_range"); + notify.setArg("[NAME]", entry->getName()); + notify.setArg("[DISTANCE]", dist_string); + chat.mText = notify; + chat.mSourceType = CHAT_SOURCE_SYSTEM; + LLFloaterChat::addChat(chat, FALSE, FALSE); + entry->setNotified(RADAR_NOTIFIED_SIM); + } + } + } + } + if (notify_chat && + (entry->getDistance() < chat_distance) && + (entry->getNotified() < RADAR_NOTIFIED_CHAT)) + { + LLChat chat; + LLUIString notify = getString("entering_chat_range"); + notify.setArg("[NAME]", entry->getName()); + notify.setArg("[DISTANCE]", dist_string); + chat.mText = notify; + chat.mSourceType = CHAT_SOURCE_SYSTEM; + LLFloaterChat::addChat(chat, FALSE, FALSE); + entry->setNotified(RADAR_NOTIFIED_CHAT); + } + } - chat.mText = notify; - chat.mSourceType = CHAT_SOURCE_SYSTEM; - LLFloaterChat::addChat(chat, FALSE, FALSE); -} + // Only display avatars in range + if (entry->getDistance() <= range) + { + // Append typing string + std::string typing = ""; + if (entry->getStatus() == RADAR_STATUS_TYPING) + { + typing = getString("is_typing")+ " "; + } + std::string mute_text = LLMuteList::getInstance()->isMuted(entry->getID()) ? getString("is_muted") : ""; + element["id"] = entry->getID(); + element["columns"][0]["column"] = "avatar_name"; + element["columns"][0]["type"] = "text"; +// [RLVa:KB] - Alternate: Imprudence-1.2.0 + //element["columns"][0]["value"] = typing + entry->getName() + " " + mute_text; + std::string fullname = (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) ? + gRlvHandler.getAnonym(fullname) : + typing + entry->getName() + " " + mute_text; + element["columns"][0]["value"] = fullname; +// [/RLVa:KB] + element["columns"][1]["column"] = "avatar_distance"; + element["columns"][1]["type"] = "text"; + element["columns"][1]["value"] = dist_string+"m"; -void PanelRadar::removeFromChatList(LLUUID agent_id) -{ - // Do we want to add a notice? - mChatAvatars.erase(agent_id); -} + mRadarList->addElement(element, ADD_BOTTOM); + } + } + mRadarList->sortItems(); + mRadarList->setScrollPos(scroll_pos); + if (mSelectedAvatar.notNull()) + { + mRadarList->selectByID(mSelectedAvatar); + } -bool PanelRadar::isTyping(LLUUID agent_id) -{ - return (mTypingAvatars.count(agent_id) > 0); -} + LLUIString av_count_string = (mRadarList->getItemCount() == 1) ? getString("avatars_in_singular") : getString("avatars_in_plural"); + av_count_string.setArg("[COUNT]", llformat("%d", mRadarList->getItemCount())); + childSetText("avatar_count", av_count_string.getString()); + updateButtonStates(); -void PanelRadar::addToTypingList(LLUUID agent_id) -{ - mTypingAvatars.insert(agent_id); + LL_DEBUGS("Radar") << "mSelectedAvatar: " << mSelectedAvatar.asString() << LL_ENDL; } - -void PanelRadar::removeFromTypingList(LLUUID agent_id) +void PanelRadar::removeDeadEntries(const std::vector& agent_ids) { - mTypingAvatars.erase(agent_id); -} - + if (agent_ids.empty()) + { + return; + } -void PanelRadar::updateSimAvList(std::vector agent_ids) -{ - std::set::iterator it; - std::vector::iterator result; - for (it = mSimAvatars.begin(); it != mSimAvatars.end(); ) + // TODO: this should really be a part of updateRadarDisplay + std::vector::const_iterator vIt; + std::map::iterator mIt; + for (mIt = mAvatars.begin(); mIt != mAvatars.end();) { - result = find(agent_ids.begin(), agent_ids.end(), *it); - if (result == agent_ids.end()) + vIt = std::find(agent_ids.begin(), agent_ids.end(), mIt->first); + if (vIt == agent_ids.end()) { - mSimAvatars.erase(it++); + // Remember, removing from the map triggers the entry's default dtor + mAvatars.erase(mIt++); } else { - it++; + mIt++; } } } - - -void PanelRadar::addToSimAvList(LLUUID agent_id, std::string distance) + +PanelRadarEntry* PanelRadar::getEntry(const LLUUID& agent_id) { - mSimAvatars.insert(agent_id); - LLChat chat; - - LLUIString notify = getString("entering_sim_range"); - notify.setArg("[NAME]", getSelectedName(agent_id)); - notify.setArg("[DISTANCE]", distance); - - chat.mText = notify; - chat.mSourceType = CHAT_SOURCE_SYSTEM; - LLFloaterChat::addChat(chat, FALSE, FALSE); + if (agent_id.isNull()) + { + return NULL; + } + else + { + std::map::iterator mIt; + mIt = mAvatars.find(agent_id); + if (mIt != mAvatars.end()) + { + return &mIt->second; + } + return NULL; + } } - -bool PanelRadar::isInSimAvList(LLUUID agent_id) +F32 PanelRadar::calculateDistance(const LLUUID& agent_id, LLVector3d agent_position) { - if (mSimAvatars.count(agent_id) > 0) + // LL only sends height value up to 1024m, try to work around it if we can by using draw distance + if (agent_position.mdV[VZ] == 0.0f) { - return true; + LLViewerObject *av_obj = gObjectList.findObject(agent_id); + if (av_obj != NULL && av_obj->isAvatar()) + { + LLVOAvatar* avatarp = (LLVOAvatar*)av_obj; + if (avatarp != NULL) + { + agent_position = avatarp->getPositionGlobal(); + } + } } - return false; + return F32(dist_vec(agent_position, gAgent.getPositionGlobal())); // don't need F64 here (what dist_vec returns) } +bool PanelRadar::isKnown(const LLUUID& agent_id) +{ + return (mAvatars.count(agent_id) > 0); +} void PanelRadar::updateButtonStates() { - bool enable = false; - bool enable_unmute = false; - bool enable_track = false; - bool enable_estate = false; - bool enable_friend = false; + static bool enable = false; + static bool enable_unmute = false; + static bool enable_track = false; + static bool enable_estate = false; + static bool enable_friend = false; + if (hasFocus()) { enable = mSelectedAvatar.notNull() ? visibleItemsSelected() : false; @@ -426,11 +409,13 @@ void PanelRadar::updateButtonStates() childSetEnabled("track_btn", enable_track); childSetEnabled("invite_btn", enable); childSetEnabled("add_btn", enable); + childSetEnabled("cam_btn", enable); childSetEnabled("freeze_btn", enable_estate); childSetEnabled("eject_btn", enable_estate); childSetEnabled("mute_btn", enable); childSetEnabled("ar_btn", enable); - childSetEnabled("estate_eject_btn", enable_estate); + //childSetEnabled("estate_eject_btn", enable_estate); + childSetEnabled("estate_ban_btn", enable_estate); if (enable_unmute) { @@ -536,21 +521,35 @@ LLUUID PanelRadar::getSelected() } -//static std::string PanelRadar::getSelectedName(const LLUUID &agent_id) { std::string agent_name; - if(gCacheName->getFullName(agent_id, agent_name) && agent_name != " ") + if(!(gCacheName->getFullName(agent_id, agent_name) && agent_name != " ")) { - return agent_name; + agent_name = getString("unknown_avatar"); } - return LLStringUtil::null; + return agent_name; +} + +void PanelRadar::sendAvatarPropertiesRequest(const LLUUID &agent_id) +{ + LL_DEBUGS("Radar") << "PanelRadar::sendAvatarPropertiesRequest()" << LL_ENDL; + LLMessageSystem *msg = gMessageSystem; + + msg->newMessageFast(_PREHASH_AvatarPropertiesRequest); + msg->nextBlockFast( _PREHASH_AgentData); + msg->addUUIDFast( _PREHASH_AgentID, gAgent.getID() ); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addUUIDFast( _PREHASH_AvatarID, agent_id); + gAgent.sendReliableMessage(); } -// -// Avatar tab -// +////////////////////////////////////////////////////////////// +// // +// * AVATAR TAB* // +// // +////////////////////////////////////////////////////////////// // static void PanelRadar::onClickIM(void* user_data) @@ -561,11 +560,10 @@ void PanelRadar::onClickIM(void* user_data) { LLUUID agent_id = item->getUUID(); gIMMgr->setFloaterOpen(TRUE); - gIMMgr->addSession(getSelectedName(agent_id), IM_NOTHING_SPECIAL, agent_id); + gIMMgr->addSession(self->getSelectedName(agent_id), IM_NOTHING_SPECIAL, agent_id); } } - // static void PanelRadar::onClickProfile(void* user_data) { @@ -578,7 +576,6 @@ void PanelRadar::onClickProfile(void* user_data) } } - // static void PanelRadar::onClickOfferTeleport(void* user_data) { @@ -597,22 +594,22 @@ void PanelRadar::onClickTeleport(void* userdata) PanelRadar *self = (PanelRadar*)userdata; LLScrollListItem *item = self->mRadarList->getFirstSelected(); - if ( item ) + if (item) { LLUUID agent_id = item->getUUID(); - std::string agent_name = getSelectedName(agent_id); - if ( !agent_name.empty() ) + std::string agent_name = self->getSelectedName(agent_id); + if (!agent_name.empty()) { LLViewerObject *av_obj = gObjectList.findObject(agent_id); - if (av_obj != NULL && av_obj->isAvatar()) - { - LLVOAvatar* avatarp = (LLVOAvatar*)av_obj; - if (avatarp != NULL) - { - LLVector3d pos = avatarp->getPositionGlobal(); - gAgent.teleportViaLocation(pos); - } - } + if (av_obj != NULL && av_obj->isAvatar()) + { + LLVOAvatar* avatarp = (LLVOAvatar*)av_obj; + if (avatarp != NULL) + { + LLVector3d pos = avatarp->getPositionGlobal(); + gAgent.teleportViaLocation(pos); + } + } } } } @@ -633,12 +630,11 @@ void PanelRadar::onClickTrack(void* user_data) if (item != NULL) { LLUUID agent_id = item->getUUID(); - LLTracker::trackAvatar(agent_id, getSelectedName(agent_id)); + LLTracker::trackAvatar(agent_id, self->getSelectedName(agent_id)); } } } - // static void PanelRadar::onClickInvite(void* user_data) { @@ -658,7 +654,6 @@ void PanelRadar::onClickInvite(void* user_data) } } - // static void PanelRadar::callback_invite_to_group(LLUUID group_id, void *user_data) { @@ -668,7 +663,6 @@ void PanelRadar::callback_invite_to_group(LLUUID group_id, void *user_data) LLFloaterGroupInvite::showForGroup(group_id, &agent_ids); } - // static void PanelRadar::onClickAddFriend(void* user_data) { @@ -677,70 +671,116 @@ void PanelRadar::onClickAddFriend(void* user_data) if (item != NULL) { LLUUID agent_id = item->getUUID(); - LLPanelFriends::requestFriendshipDialog(agent_id, getSelectedName(agent_id)); + LLPanelFriends::requestFriendshipDialog(agent_id, self->getSelectedName(agent_id)); } } +////////////////////////////////////////////////////////////// +// // +// * ESTATE TAB * // +// // +////////////////////////////////////////////////////////////// -// -// Estate tab -// +// static +void PanelRadar::onClickCam(void* user_data) +{ + PanelRadar *self = (PanelRadar*)user_data; + self->lookAtAvatar(self->getSelected()); +} +void PanelRadar::lookAtAvatar(const LLUUID& agent_id) +{ + LLViewerObject* voavatar = gObjectList.findObject(agent_id); + if (voavatar && voavatar->isAvatar()) + { + gAgent.setFocusOnAvatar(FALSE, FALSE); + gAgent.changeCameraToThirdPerson(); + gAgent.setFocusGlobal(voavatar->getPositionGlobal(), agent_id); + gAgent.setCameraPosAndFocusGlobal(voavatar->getPositionGlobal() + + LLVector3d(3.5,1.35,0.75) * voavatar->getRotation(), + voavatar->getPositionGlobal(), + agent_id ); + } +} //static bool PanelRadar::callbackFreeze(const LLSD& notification, const LLSD& response, PanelRadar *self) { S32 option = LLNotification::getSelectedOption(notification, response); - if ( option == 0 ) + if (option == 0) { sendFreeze(self->mSelectedAvatar, true); } - else if ( option == 1 ) + else if (option == 1) { sendFreeze(self->mSelectedAvatar, false); } return false; } - //static bool PanelRadar::callbackEject(const LLSD& notification, const LLSD& response, PanelRadar *self) { S32 option = LLNotification::getSelectedOption(notification, response); - if ( option == 0 ) + if (option == 0) { sendEject(self->mSelectedAvatar, false); } - else if ( option == 1 ) + else if (option == 1) { sendEject(self->mSelectedAvatar, true); } return false; } - //static -bool PanelRadar::callbackEjectFromEstate(const LLSD& notification, const LLSD& response, PanelRadar *self) +//bool PanelRadar::callbackEjectFromEstate(const LLSD& notification, const LLSD& response, PanelRadar *self) +//{ +// S32 option = LLNotification::getSelectedOption(notification, response); +// if (option == 0) +// { +// strings_t strings; +// strings.push_back(self->getSelected().asString()); +// sendEstateOwnerMessage(gMessageSystem, "kickestate", LLFloaterRegionInfo::getLastInvoice(), strings); +// } +// return false; +//} + +// static +bool PanelRadar::callbackBanFromEstate(const LLSD& notification, const LLSD& response, PanelRadar *self) { S32 option = LLNotification::getSelectedOption(notification, response); - if ( option == 0 ) + if (option == 0) { - cmdEstateEject(self->mSelectedAvatar); - } - else if ( option == 1 ) + LLPanelEstateInfo::sendEstateAccessDelta(ESTATE_ACCESS_BANNED_AGENT_ADD | ESTATE_ACCESS_ALLOWED_AGENT_REMOVE | ESTATE_ACCESS_NO_REPLY, self->getSelected()); + } + else if (option == 1) { - cmdEstateBan(self->mSelectedAvatar); + LLViewerRegion* regionp = gAgent.getRegion(); + if (regionp) + { + U32 flags = ESTATE_ACCESS_BANNED_AGENT_ADD | ESTATE_ACCESS_ALLOWED_AGENT_REMOVE | ESTATE_ACCESS_NO_REPLY; + if (regionp->getOwner() == gAgent.getID() || gAgent.isGodlike()) + { + flags |= ESTATE_ACCESS_APPLY_TO_ALL_ESTATES; + } + else if (regionp->isEstateManager()) + { + flags |= ESTATE_ACCESS_APPLY_TO_MANAGED_ESTATES; + } + LLPanelEstateInfo::sendEstateAccessDelta(flags, self->getSelected()); + } } return false; } - +// static void PanelRadar::onClickFreeze(void *user_data) { PanelRadar *self = (PanelRadar*)user_data; LLSD args; - args["AVATAR_NAME"] = getSelectedName(self->mSelectedAvatar); + args["AVATAR_NAME"] = self->getSelectedName(self->mSelectedAvatar); LLNotifications::instance().add("FreezeAvatarFullname", args, LLSD(), @@ -748,20 +788,28 @@ void PanelRadar::onClickFreeze(void *user_data) } -//static -void PanelRadar::onClickEject(void *user_data) +// static +void PanelRadar::onClickUnfreeze(void *user_data) { PanelRadar *self = (PanelRadar*)user_data; - LLSD args; - args["AVATAR_NAME"] = getSelectedName(self->mSelectedAvatar); - LLNotifications::instance().add("EjectAvatarFullname", - args, - LLSD(), - boost::bind(&callbackEject, _1, _2, self)); + sendFreeze(self->getSelected(), false); } //static +//void PanelRadar::onClickEjectFromEstate(void *user_data) +//{ +// PanelRadar *self = (PanelRadar*)user_data; +// LLSD args; +// args["AVATAR_NAME"] = self->getSelectedName(self->mSelectedAvatar); +// LLNotifications::instance().add("EjectAvatarFullnameNoBan", +// args, +// LLSD(), +// boost::bind(&callbackEjectFromEstate, _1, _2, self)); +//} + + +//static void PanelRadar::onClickMute(void *user_data) { PanelRadar *self = (PanelRadar*)user_data; @@ -769,7 +817,7 @@ void PanelRadar::onClickMute(void *user_data) if (item != NULL) { LLUUID agent_id = item->getUUID(); - std::string agent_name = getSelectedName(agent_id); + std::string agent_name = self->getSelectedName(agent_id); if (LLMuteList::getInstance()->isMuted(agent_id)) { //LLMute mute(agent_id, agent_name, LLMute::AGENT); @@ -793,7 +841,7 @@ void PanelRadar::onClickUnmute(void *user_data) if (item != NULL) { LLUUID agent_id = item->getUUID(); - std::string agent_name = getSelectedName(agent_id); + std::string agent_name = self->getSelectedName(agent_id); if (LLMuteList::getInstance()->isMuted(agent_id)) { LLMute mute(agent_id, agent_name, LLMute::AGENT); @@ -810,15 +858,15 @@ void PanelRadar::onClickUnmute(void *user_data) //static -void PanelRadar::onClickEjectFromEstate(void *user_data) +void PanelRadar::onClickEject(void *user_data) { PanelRadar *self = (PanelRadar*)user_data; LLSD args; - args["EVIL_USER"] = getSelectedName(self->mSelectedAvatar); + args["EVIL_USER"] = self->getSelectedName(self->mSelectedAvatar); LLNotifications::instance().add("EstateKickUser", args, LLSD(), - boost::bind(&callbackEjectFromEstate, _1, _2, self)); + boost::bind(&callbackEject, _1, _2, self)); } @@ -835,6 +883,16 @@ void PanelRadar::onClickAR(void *user_data) } +//static +void PanelRadar::onClickBanFromEstate(void *user_data) +{ + PanelRadar *self = (PanelRadar*)user_data; + LLSD args; + args["ALL_ESTATES"] = "all estates"; + LLNotifications::instance().add("EstateBannedAgentAdd", args, LLSD(), boost::bind(&callbackBanFromEstate, _1, _2, self)); +} + + // static void PanelRadar::cmdEstateEject(const LLUUID &avatar) { @@ -971,3 +1029,37 @@ void PanelRadar::sendEstateBan(const LLUUID& agent) gAgent.sendReliableMessage(); } + +//typedef std::vector strings_t; +//static void sendEstateOwnerMessage( +// LLMessageSystem* msg, +// const std::string& request, +// const LLUUID& invoice, +// const strings_t& strings) +//{ +// llinfos << "Sending estate request '" << request << "'" << llendl; +// msg->newMessage("EstateOwnerMessage"); +// msg->nextBlockFast(_PREHASH_AgentData); +// msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); +// msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); +// msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); //not used +// msg->nextBlock("MethodData"); +// msg->addString("Method", request); +// msg->addUUID("Invoice", invoice); +// if(strings.empty()) +// { +// msg->nextBlock("ParamList"); +// msg->addString("Parameter", NULL); +// } +// else +// { +// strings_t::const_iterator it = strings.begin(); +// strings_t::const_iterator end = strings.end(); +// for(; it != end; ++it) +// { +// msg->nextBlock("ParamList"); +// msg->addString("Parameter", *it); +// } +// } +// msg->sendReliable(gAgent.getRegion()->getHost()); +//} diff --git a/linden/indra/newview/panelradar.h b/linden/indra/newview/panelradar.h index de7760f..af0ca2a 100644 --- a/linden/indra/newview/panelradar.h +++ b/linden/indra/newview/panelradar.h @@ -33,6 +33,7 @@ #include "llpanel.h" #include "llscrolllistctrl.h" +class PanelRadarEntry; class PanelRadar : public LLPanel { @@ -42,44 +43,44 @@ public: BOOL postBuild(); - // returns true if agent_id belongs to an Imprudence developer - static bool isImpDev(LLUUID agent_id); - + // Returns true if agent_id belongs to an Imprudence developer + bool isImpDev(const LLUUID& agent_id); + // Change the camera focus to an avatar + void lookAtAvatar(const LLUUID& agent_id); + + // Returns UUID of currently selected avatar LLUUID getSelected(); - void addToTypingList(LLUUID agent_id); - void removeFromTypingList(LLUUID agent_id); - + // Updates the radar button states void updateButtonStates(); - void populateRadar(); + // Update the list of known avatars + void updateRadarInfo(); + // Update the radar UI. Call updateRadarInfo first + void updateRadarDisplay(); + + // Returns PanelRadarEntry* if key is found, NULL if not + PanelRadarEntry* getEntry(const LLUUID& agent_id); + // Returns true if avatar is in the radar's list + bool isKnown(const LLUUID& agent_id); private: - // TODO: move all this info into its own object. It's stupid - // and bug-prone to keep it all in separate containers, but - // I want to get this out for 1.2 -- McCabe - std::set mChatAvatars; - std::set mTypingAvatars; - std::set mSimAvatars; + std::map mAvatars; + + // Returns your distance from an avatar's position + F32 calculateDistance(const LLUUID& agent_id, LLVector3d agent_position); + // Removes avatar IDs no longer known to the viewer + void removeDeadEntries(const std::vector& agent_ids); LLScrollListCtrl* mRadarList; LLUUID mSelectedAvatar; - void updateChatList(std::vector agent_ids); - bool isInChatList(LLUUID agent_id); - void addToChatList(LLUUID agent_id, std::string distance); - void removeFromChatList(LLUUID agent_id); - - bool isInSimAvList(LLUUID agent_id); - void addToSimAvList(LLUUID agent_id, std::string distance); - void updateSimAvList(std::vector agent_ids); - - bool isTyping(LLUUID agent_id); - bool visibleItemsSelected() const; bool isKickable(const LLUUID &agent_id); - static std::string getSelectedName(const LLUUID &agent_id); + std::string getSelectedName(const LLUUID &agent_id); + + void sendAvatarPropertiesRequest(const LLUUID &agent_id); static void onUseRadarList(LLUICtrl* ctrl, void* user_data); static void onRangeChange(LLFocusableElement* focus, void* user_data); @@ -93,25 +94,28 @@ private: static void onClickInvite(void* user_data); static void callback_invite_to_group(LLUUID group_id, void *user_data); + static void onClickCam(void* user_data); static void onClickFreeze(void *user_data); + static void onClickUnfreeze(void *user_data); static void onClickEject(void *user_data); static void onClickMute(void *user_data); static void onClickUnmute(void *user_data); static void onClickAR(void *user_data); - static void onClickEjectFromEstate(void *user_data); + //static void onClickEjectFromEstate(void *user_data); Not working yet + static void onClickBanFromEstate(void *user_data); static void callbackAR(void *user_data); static bool callbackFreeze(const LLSD& notification, const LLSD& response, PanelRadar *self); static bool callbackEject(const LLSD& notification, const LLSD& response, PanelRadar *self); - static bool callbackEjectFromEstate(const LLSD& notification, const LLSD& response, PanelRadar *self); + //static bool callbackEjectFromEstate(const LLSD& notification, const LLSD& response, PanelRadar *self); + static bool callbackBanFromEstate(const LLSD& notification, const LLSD& response, PanelRadar *self); - static void sendFreeze(const LLUUID &avatar, bool); - static void sendEject(const LLUUID &avatar, bool); + static void sendFreeze(const LLUUID& avatar, bool freeze); + static void sendEject(const LLUUID& avatar, bool ban); static void cmdEstateEject(const LLUUID &avatar); static void cmdEstateBan(const LLUUID &avatar); static void sendEstateBan(const LLUUID& agent); static void sendEstateMessage(const char* request, const LLUUID &target); - }; diff --git a/linden/indra/newview/panelradarentry.cpp b/linden/indra/newview/panelradarentry.cpp new file mode 100644 index 0000000..8accd29 --- /dev/null +++ b/linden/indra/newview/panelradarentry.cpp @@ -0,0 +1,85 @@ +/** + * @file panelradarentry.cpp + * @brief PanelRadarEntry class (container for nearby agents) + * + * Copyright (c) 2010, McCabe Maxsted + * + * The source code in this file ("Source Code") is provided to you + * under the terms of the GNU General Public License, version 2.0 + * ("GPL"). Terms of the GPL can be found in doc/GPL-license.txt in + * this distribution, or online at + * http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL SOURCE CODE IS PROVIDED "AS IS." THE AUTHOR MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + */ + +#include "llviewerprecompiledheaders.h" + +#include "panelradarentry.h" + +const F32 RADAR_STATUS_TIMEOUT = 30.0f; // 30 seconds seems to be a good timeout + +PanelRadarEntry::PanelRadarEntry(const LLUUID& agent_id, const std::string& agent_name, const F32& distance, const LLVector3d& position, const RADAR_STATUS& status, const RADAR_NOTIFIED& notified) : + mID(agent_id), + mName(agent_name), + mDistance(distance), + mPosition(position), + mStatus(status), + mNotified(notified), + mStatusTimer() +{ + mStatusTimer.setTimerExpirySec(RADAR_STATUS_TIMEOUT); +} + +void PanelRadarEntry::setName(const std::string& name) +{ + mName = name; +} + +void PanelRadarEntry::setDistance(const F32& distance) +{ + mDistance = distance; +} + +void PanelRadarEntry::setPosition(const LLVector3d& position) +{ + mPosition = position; +} + +void PanelRadarEntry::setStatus(const RADAR_STATUS& status) +{ + if (status <= RADAR_STATUS_AWAY) + { + mStatus = status; + + if (mStatus != RADAR_STATUS_NONE || mStatusTimer.hasExpired()) + { + mStatusTimer.start(); + mStatusTimer.setTimerExpirySec(RADAR_STATUS_TIMEOUT); + } + else + { + mStatusTimer.stop(); + } + } +} + +void PanelRadarEntry::setNotified(const RADAR_NOTIFIED& notified) +{ + if (notified <= RADAR_NOTIFIED_SIM) + { + mNotified = notified; + } +} diff --git a/linden/indra/newview/panelradarentry.h b/linden/indra/newview/panelradarentry.h new file mode 100644 index 0000000..b54e1a6 --- /dev/null +++ b/linden/indra/newview/panelradarentry.h @@ -0,0 +1,83 @@ +/** + * @file panelradarentry.h + * @brief PanelRadarEntry class (container for nearby agents) + * + * Copyright (c) 2010, McCabe Maxsted + * + * The source code in this file ("Source Code") is provided to you + * under the terms of the GNU General Public License, version 2.0 + * ("GPL"). Terms of the GPL can be found in doc/GPL-license.txt in + * this distribution, or online at + * http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL SOURCE CODE IS PROVIDED "AS IS." THE AUTHOR MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + */ + + +#ifndef PANELRADARENTRY_H +#define PANELRADARENTRY_H + + +#include "llframetimer.h" + +enum RADAR_STATUS +{ + RADAR_STATUS_NONE, + RADAR_STATUS_TYPING, + RADAR_STATUS_EMITTING_SOUNDS, + RADAR_STATUS_EMITTING_PARTICLES, + RADAR_STATUS_FLYING, + RADAR_STATUS_BUSY, + RADAR_STATUS_AWAY +}; + +enum RADAR_NOTIFIED +{ + RADAR_NOTIFIED_NONE, + RADAR_NOTIFIED_SIM, + RADAR_NOTIFIED_CHAT +}; + + +class PanelRadarEntry +{ +public: + PanelRadarEntry(const LLUUID& agent_id, const std::string& agent_name, const F32& distance, const LLVector3d& position, const RADAR_STATUS& status, const RADAR_NOTIFIED& notified); + + LLUUID getID() { return mID; } + std::string getName() { return mName; } + F32 getDistance() { return mDistance; } + LLVector3d getPosition() { return mPosition; } + RADAR_STATUS getStatus() { return mStatus; } + RADAR_NOTIFIED getNotified() { return mNotified; } + LLFrameTimer getStatusTimer(){ return mStatusTimer; } + + void setName(const std::string& name); + void setDistance(const F32& distance); + void setPosition(const LLVector3d& position); + void setStatus(const RADAR_STATUS& status); + void setNotified(const RADAR_NOTIFIED& notified); + +private: + LLUUID mID; + std::string mName; + F32 mDistance; + LLVector3d mPosition; + RADAR_STATUS mStatus; + RADAR_NOTIFIED mNotified; + LLFrameTimer mStatusTimer; +}; + +#endif // PANELRADARENTRY_H diff --git a/linden/indra/newview/skins/default/xui/en-us/panel_radar.xml b/linden/indra/newview/skins/default/xui/en-us/panel_radar.xml index 1f1749e..969ddd8 100644 --- a/linden/indra/newview/skins/default/xui/en-us/panel_radar.xml +++ b/linden/indra/newview/skins/default/xui/en-us/panel_radar.xml @@ -22,28 +22,22 @@ [NAME] has entered the sim ([DISTANCE]m) - avatar in + [COUNT] avatar in - avatars in + [COUNT] avatars in + + + (Unknown) - - 0 - - - - avatars in + 0 avatars in + +