aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra
diff options
context:
space:
mode:
authorMcCabe Maxsted2010-06-05 02:19:12 -0700
committerJacek Antonelli2010-06-19 02:43:30 -0500
commitfa004431e6dc454f1ceacace1234c39bb19f7d89 (patch)
tree51dd85d9c162284a8a3160293aae5459b72f81a2 /linden/indra
parentMake sure we only create menus once per session (diff)
downloadmeta-impy-fa004431e6dc454f1ceacace1234c39bb19f7d89.zip
meta-impy-fa004431e6dc454f1ceacace1234c39bb19f7d89.tar.gz
meta-impy-fa004431e6dc454f1ceacace1234c39bb19f7d89.tar.bz2
meta-impy-fa004431e6dc454f1ceacace1234c39bb19f7d89.tar.xz
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)
Diffstat (limited to 'linden/indra')
-rw-r--r--linden/indra/newview/CMakeLists.txt2
-rw-r--r--linden/indra/newview/app_settings/settings.xml11
-rw-r--r--linden/indra/newview/llnetmap.cpp4
-rw-r--r--linden/indra/newview/llviewermessage.cpp13
-rw-r--r--linden/indra/newview/panelradar.cpp672
-rw-r--r--linden/indra/newview/panelradar.h64
-rw-r--r--linden/indra/newview/panelradarentry.cpp85
-rw-r--r--linden/indra/newview/panelradarentry.h83
-rw-r--r--linden/indra/newview/skins/default/xui/en-us/panel_radar.xml32
9 files changed, 627 insertions, 339 deletions
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
461 llxmlrpctransaction.cpp 461 llxmlrpctransaction.cpp
462 noise.cpp 462 noise.cpp
463 panelradar.cpp 463 panelradar.cpp
464 panelradarentry.cpp
464 pipeline.cpp 465 pipeline.cpp
465 primbackup.cpp 466 primbackup.cpp
466 rlvhandler.cpp 467 rlvhandler.cpp
@@ -894,6 +895,7 @@ set(viewer_HEADER_FILES
894 macmain.h 895 macmain.h
895 noise.h 896 noise.h
896 panelradar.h 897 panelradar.h
898 panelradarentry.h
897 pipeline.h 899 pipeline.h
898 primbackup.h 900 primbackup.h
899 randgauss.h 901 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 @@
48 <key>Value</key> 48 <key>Value</key>
49 <string></string> 49 <string></string>
50 </map> 50 </map>
51 <key>ChatDistance</key>
52 <map>
53 <key>Comment</key>
54 <string>Default chat distance in meters</string>
55 <key>Persist</key>
56 <integer>1</integer>
57 <key>Type</key>
58 <string>U32</string>
59 <key>Value</key>
60 <real>20</real>
61 </map>
51 <key>CmdLineCacheLocation</key> 62 <key>CmdLineCacheLocation</key>
52 <map> 63 <map>
53 <key>Comment</key> 64 <key>Comment</key>
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()
372 { 372 {
373 glyph_color = muted_color; 373 glyph_color = muted_color;
374 } 374 }
375 else if (PanelRadar::isImpDev(avatar_ids[i])) 375 else if (LLFloaterMap::getInstance()->getRadar()->isImpDev(avatar_ids[i]))
376 { 376 {
377 glyph_color = imp_dev_color; 377 glyph_color = imp_dev_color;
378 } 378 }
@@ -516,7 +516,7 @@ void LLNetMap::draw()
516 516
517 LLView::draw(); 517 LLView::draw();
518 518
519 LLFloaterMap::getInstance()->getRadar()->populateRadar(); 519 LLFloaterMap::getInstance()->getRadar()->updateRadarInfo();
520} 520}
521 521
522void LLNetMap::reshape(S32 width, S32 height, BOOL called_from_parent) 522void 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 @@
140 140
141#include "llwlparammanager.h" 141#include "llwlparammanager.h"
142#include "llwaterparammanager.h" 142#include "llwaterparammanager.h"
143#include "panelradarentry.h"
143 144
144#include <boost/tokenizer.hpp> 145#include <boost/tokenizer.hpp>
145#include <boost/regex.hpp> // Boost Reg Expresions 146#include <boost/regex.hpp> // Boost Reg Expresions
@@ -2785,7 +2786,11 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
2785 2786
2786 if (LLFloaterMap::getInstance()) 2787 if (LLFloaterMap::getInstance())
2787 { 2788 {
2788 LLFloaterMap::getInstance()->getRadar()->addToTypingList(from_id); 2789 PanelRadarEntry* entry = LLFloaterMap::getInstance()->getRadar()->getEntry(from_id);
2790 if (entry)
2791 {
2792 entry->setStatus(RADAR_STATUS_TYPING);
2793 }
2789 } 2794 }
2790 2795
2791 return; 2796 return;
@@ -2802,7 +2807,11 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
2802 2807
2803 if (LLFloaterMap::getInstance()) 2808 if (LLFloaterMap::getInstance())
2804 { 2809 {
2805 LLFloaterMap::getInstance()->getRadar()->removeFromTypingList(from_id); 2810 PanelRadarEntry* entry = LLFloaterMap::getInstance()->getRadar()->getEntry(from_id);
2811 if (entry)
2812 {
2813 entry->setStatus(RADAR_STATUS_NONE);
2814 }
2806 } 2815 }
2807 2816
2808 return; 2817 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 @@
36#include "llfloaterfriends.h" 36#include "llfloaterfriends.h"
37#include "llfloatergroupinvite.h" 37#include "llfloatergroupinvite.h"
38#include "llfloatergroups.h" 38#include "llfloatergroups.h"
39#include "llfloatermap.h"
40#include "llfloaterregioninfo.h"
39#include "llfloaterreporter.h" 41#include "llfloaterreporter.h"
40#include "llimview.h" 42#include "llimview.h"
41#include "llmutelist.h" 43#include "llmutelist.h"
@@ -53,6 +55,7 @@
53#include "llviewerwindow.h" 55#include "llviewerwindow.h"
54#include "llvoavatar.h" 56#include "llvoavatar.h"
55#include "llworld.h" 57#include "llworld.h"
58#include "panelradarentry.h"
56 59
57 60
58PanelRadar::PanelRadar() 61PanelRadar::PanelRadar()
@@ -61,10 +64,6 @@ PanelRadar::PanelRadar()
61 mSelectedAvatar(LLUUID::null) 64 mSelectedAvatar(LLUUID::null)
62{ 65{
63 LLUICtrlFactory::getInstance()->buildPanel(this, "panel_radar.xml"); 66 LLUICtrlFactory::getInstance()->buildPanel(this, "panel_radar.xml");
64
65 mChatAvatars.clear();
66 mTypingAvatars.clear();
67 mSimAvatars.clear();
68} 67}
69 68
70 69
@@ -81,28 +80,27 @@ BOOL PanelRadar::postBuild()
81 childSetAction("track_btn", onClickTrack, this); 80 childSetAction("track_btn", onClickTrack, this);
82 childSetAction("invite_btn", onClickInvite, this); 81 childSetAction("invite_btn", onClickInvite, this);
83 childSetAction("add_btn", onClickAddFriend, this); 82 childSetAction("add_btn", onClickAddFriend, this);
83 childSetAction("cam_btn", onClickCam, this);
84 childSetAction("freeze_btn", onClickFreeze, this); 84 childSetAction("freeze_btn", onClickFreeze, this);
85 childSetAction("eject_btn", onClickEject, this); 85 childSetAction("eject_btn", onClickEject, this);
86 childSetAction("mute_btn", onClickMute, this); 86 childSetAction("mute_btn", onClickMute, this);
87 childSetAction("unmute_btn", onClickUnmute, this); 87 childSetAction("unmute_btn", onClickUnmute, this);
88 childSetAction("ar_btn", onClickAR, this); 88 childSetAction("ar_btn", onClickAR, this);
89 childSetAction("estate_eject_btn", onClickEjectFromEstate, this); 89 //childSetAction("estate_eject_btn", onClickEjectFromEstate, this);
90 childSetAction("estate_ban_btn", onClickBanFromEstate, this);
90 91
91 setDefaultBtn("im_btn"); 92 setDefaultBtn("im_btn");
92 93
93 populateRadar(); 94 updateRadarInfo();
94 95
95 return TRUE; 96 return TRUE;
96} 97}
97 98
98
99PanelRadar::~PanelRadar() 99PanelRadar::~PanelRadar()
100{ 100{
101} 101}
102 102
103 103bool PanelRadar::isImpDev(const LLUUID& agent_id)
104//static
105bool PanelRadar::isImpDev(LLUUID agent_id)
106{ 104{
107 // We use strings here as avatar keys change across grids. 105 // We use strings here as avatar keys change across grids.
108 // Feel free to add/remove yourself. 106 // Feel free to add/remove yourself.
@@ -112,300 +110,285 @@ bool PanelRadar::isImpDev(LLUUID agent_id)
112 agent_name == "Armin Weatherwax"); 110 agent_name == "Armin Weatherwax");
113} 111}
114 112
115 113void PanelRadar::updateRadarInfo()
116void PanelRadar::populateRadar()
117{ 114{
118 if (!getVisible()) 115 if (!getVisible())
119 { 116 {
120 return; 117 return;
121 } 118 }
122 119
123 if (visibleItemsSelected()) 120 // find what avatars we can know about
124 {
125 mSelectedAvatar = mRadarList->getFirstSelected()->getUUID();
126 }
127 else
128 {
129 mSelectedAvatar.setNull();
130 }
131
132 S32 scroll_pos = mRadarList->getScrollPos();
133
134 // clear count
135 std::stringstream avatar_count;
136 avatar_count.str("");
137
138 // find what avatars you can see
139 F32 range = gSavedSettings.getF32("NearMeRange");
140 LLVector3d current_pos = gAgent.getPositionGlobal();
141 std::vector<LLUUID> avatar_ids; 121 std::vector<LLUUID> avatar_ids;
142 std::vector<LLVector3d> positions; 122 std::vector<LLVector3d> positions;
143 LLWorld::getInstance()->getAvatars(&avatar_ids, &positions); 123 LLWorld::getInstance()->getAvatars(&avatar_ids, &positions);
144 124
145 LLSD element;
146
147 mRadarList->deleteAllItems();
148
149 if (!avatar_ids.empty()) 125 if (!avatar_ids.empty())
150 { 126 {
151 for (U32 i=0; i<avatar_ids.size(); i++) 127 for (U32 i=0; i<avatar_ids.size(); i++)
152 { 128 {
153 if (avatar_ids[i] == gAgent.getID() || 129 // This actually happens sometimes O.o
154 avatar_ids[i].isNull()) 130 if (avatar_ids[i] == gAgent.getID() || avatar_ids[i].isNull())
155 { 131 {
156 continue; 132 continue;
157 } 133 }
158 134
159 // Add to list only if we get their name 135 // Determine if they're in the list already--getEntry checks for null keys
160 std::string fullname = getSelectedName(avatar_ids[i]); 136 PanelRadarEntry* entry = getEntry(avatar_ids[i]);
161 if (!fullname.empty())
162 {
163 bool notify_chat = gSavedSettings.getBOOL("MiniMapNotifyChatRange");
164 bool notify_sim = gSavedSettings.getBOOL("MiniMapNotifySimRange");
165 // [RLVa:KB] - Alternate: Imprudence-1.2.0
166 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
167 {
168 fullname = gRlvHandler.getAnonym(fullname);
169 notify_chat = false;
170 notify_sim = false;
171 }
172 // [/RLVa:KB]
173 137
174 // check if they're in certain ranges and notify user if we've enabled that 138 // If they aren't, create a new entry
175 LLVector3d temp = positions[i]; 139 // If they are, see if we need to update any values
176 if (positions[i].mdV[VZ] == 0.0f) // LL only sends height value up to 1024m, try to work around it 140 // List them as "(Unknown)" if we can't get their name
177 { 141 if (!entry)
178 LLViewerObject *av_obj = gObjectList.findObject(avatar_ids[i]); 142 {
179 if (av_obj != NULL && av_obj->isAvatar()) 143 mAvatars.insert(std::pair<LLUUID, PanelRadarEntry>(avatar_ids[i], PanelRadarEntry(avatar_ids[i],
180 { 144 getSelectedName(avatar_ids[i]),
181 LLVOAvatar* avatarp = (LLVOAvatar*)av_obj; 145 calculateDistance(avatar_ids[i], positions[i]),
182 if (avatarp != NULL) 146 positions[i],
183 { 147 RADAR_STATUS_NONE,
184 temp = avatarp->getPositionGlobal(); 148 RADAR_NOTIFIED_NONE)
185 } 149 ));
186 } 150 }
187 } 151 else
188 F64 distance = dist_vec(temp, current_pos); 152 {
189 // we round for accuracy when avs tp in 153 if (entry->getName() == getString("unknown_avatar"))
190 std::string dist_string = llformat("%.1f", llround((F32)distance, 0.1f));
191
192 /*llinfos << "Avatar :" << fullname << " Position: " << positions[i] << " Your Position: "
193 << current_pos << " Distance: " << distance << llendl;*/
194
195 if (notify_chat)
196 {
197 if (distance < 20.0f)
198 {
199 if (!isInChatList(avatar_ids[i]))
200 {
201 addToChatList(avatar_ids[i], dist_string);
202 }
203 }
204 else
205 {
206 if (isInChatList(avatar_ids[i]))
207 {
208 removeFromChatList(avatar_ids[i]);
209 }
210 }
211 updateChatList(avatar_ids);
212 }
213 else if (!mChatAvatars.empty())
214 {
215 mChatAvatars.clear();
216 }
217
218 if (notify_sim)
219 { 154 {
220 if (!isInChatList(avatar_ids[i]) && !isInSimAvList(avatar_ids[i])) 155 // Try to find the name again
221 { 156 entry->setName(getSelectedName(avatar_ids[i]));
222 LLViewerObject *av_obj = gObjectList.findObject(avatar_ids[i]);
223 if (av_obj != NULL && av_obj->isAvatar())
224 {
225 LLVOAvatar* avatarp = (LLVOAvatar*)av_obj;
226 if (avatarp != NULL)
227 {
228 if (avatarp->getRegion() == gAgent.getRegion())
229 {
230 addToSimAvList(avatar_ids[i], dist_string);
231 }
232 }
233 }
234 }
235 updateSimAvList(avatar_ids);
236 } 157 }
237 else if (!mSimAvatars.empty()) 158 if (entry->getPosition() != positions[i])
238 { 159 {
239 mSimAvatars.clear(); 160 entry->setPosition(positions[i]);
240 } 161 }
241 162 if (entry->getStatusTimer().hasExpired())
242 // only display avatars in range
243 if (distance <= range)
244 { 163 {
245 // append typing string 164 entry->setStatus(RADAR_STATUS_NONE);
246 std::string typing = "";
247 if (isTyping(avatar_ids[i]))
248 {
249 typing = getString("is_typing")+ " ";
250 }
251
252 std::string mute_text = LLMuteList::getInstance()->isMuted(avatar_ids[i]) ? getString("is_muted") : "";
253 element["id"] = avatar_ids[i];
254 element["columns"][0]["column"] = "avatar_name";
255 element["columns"][0]["type"] = "text";
256 element["columns"][0]["value"] = typing + fullname + " " + mute_text;
257 element["columns"][1]["column"] = "avatar_distance";
258 element["columns"][1]["type"] = "text";
259 element["columns"][1]["value"] = dist_string+"m";
260
261 mRadarList->addElement(element, ADD_BOTTOM);
262 } 165 }
166 entry->setDistance(calculateDistance(avatar_ids[i], positions[i]));
263 } 167 }
264 } 168 }
265 169 removeDeadEntries(avatar_ids);
266 mRadarList->sortItems();
267 mRadarList->setScrollPos(scroll_pos);
268 if (mSelectedAvatar.notNull())
269 {
270 mRadarList->selectByID(mSelectedAvatar);
271 }
272 avatar_count << (int)avatar_ids.size();
273 childSetText("avatars_in", ((int)avatar_ids.size() > 1) ?
274 getString("avatars_in_plural") :
275 getString("avatars_in_singular"));
276 } 170 }
277 else 171 else // avatar_ids empty
278 { 172 {
279 mTypingAvatars.clear(); 173 mRadarList->deleteAllItems();
280 mRadarList->addCommentText(getString("no_one_near"), ADD_TOP); 174 mRadarList->addCommentText(getString("no_one_near"), ADD_TOP);
281 avatar_count << "0"; 175 LLUIString av_count_string = getString("avatars_in_plural");
282 childSetText("avatars_in", getString("avatars_in_plural")); 176 av_count_string.setArg("[COUNT]", "0");
177 childSetText("avatar_count", av_count_string.getString());
178 return;
283 } 179 }
284 180
285 childSetText("lblAvatarCount", avatar_count.str()); 181 updateRadarDisplay();
286
287 updateButtonStates();
288
289 //llinfos << "mSelectedAvatar: " << mSelectedAvatar.asString() << llendl;
290} 182}
291 183
292 184void PanelRadar::updateRadarDisplay()
293void PanelRadar::updateChatList(std::vector<LLUUID> agent_ids)
294{ 185{
295 std::set<LLUUID>::iterator it; 186 if (visibleItemsSelected())
296 std::vector<LLUUID>::iterator result;
297 for (it = mChatAvatars.begin(); it != mChatAvatars.end(); )
298 { 187 {
299 result = find(agent_ids.begin(), agent_ids.end(), *it); 188 mSelectedAvatar = mRadarList->getFirstSelected()->getUUID();
300 if (result == agent_ids.end()) 189 }
301 { 190 else
302 mChatAvatars.erase(it++); 191 {
303 } 192 mSelectedAvatar.setNull();
304 else
305 {
306 it++;
307 }
308 } 193 }
309}
310 194
195 S32 scroll_pos = mRadarList->getScrollPos();
311 196
312bool PanelRadar::isInChatList(LLUUID agent_id) 197 LLSD element;
313{
314 return (mChatAvatars.count(agent_id) > 0);
315}
316 198
199 // Zap all the avie names. Zap zap zap!
200 mRadarList->deleteAllItems();
317 201
318void PanelRadar::addToChatList(LLUUID agent_id, std::string distance) 202 U32 chat_distance = gSavedSettings.getU32("ChatDistance");
319{ 203 F32 range = gSavedSettings.getF32("NearMeRange");
320 mChatAvatars.insert(agent_id); 204 bool notify_chat = gSavedSettings.getBOOL("MiniMapNotifyChatRange");
321 LLChat chat; 205 bool notify_sim = gSavedSettings.getBOOL("MiniMapNotifySimRange");
206// [RLVa:KB] - Alternate: Imprudence-1.2.0
207 if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
208 {
209 notify_chat = false;
210 notify_sim = false;
211 }
212// [/RLVa:KB]
322 213
323 LLUIString notify = getString("entering_chat_range"); 214 std::map<LLUUID, PanelRadarEntry>::iterator mIt;
324 notify.setArg("[NAME]", getSelectedName(agent_id)); 215 for (mIt = mAvatars.begin(); mIt != mAvatars.end(); ++mIt)
325 notify.setArg("[DISTANCE]", distance); 216 {
217 PanelRadarEntry* entry = &mIt->second;
218
219 LL_DEBUGS("Radar") << "Avatar :" << entry->getName()
220 << " Position: " << entry->getPosition()
221 << " Your Position: " << gAgent.getPositionGlobal()
222 << " Distance: " << entry->getDistance()
223 << " Status: " << entry->getStatus()
224 << " Notified: " << entry->getNotified()
225 << " Timer Seconds: " << entry->getStatusTimer().getElapsedTimeF32()
226 << LL_ENDL;
227
228 // Check if they're in certain ranges and notify user if we've enabled that, starting with chat range
229 // We round for accuracy when avs tp in
230 std::string dist_string = llformat("%.1f", llround(entry->getDistance(), 0.1f));
231
232 // Don't notify if we don't know their name. It takes a few seconds for names to load on OpenSim, anyway
233 if (entry->getName() != getString("unknown_avatar"))
234 {
235 if (notify_sim &&
236 (entry->getNotified() < RADAR_NOTIFIED_SIM))
237 {
238 LLViewerObject *av_obj = gObjectList.findObject(entry->getID());
239 if (av_obj != NULL && av_obj->isAvatar())
240 {
241 LLVOAvatar* avatarp = (LLVOAvatar*)av_obj;
242 if (avatarp != NULL)
243 {
244 if (avatarp->getRegion() == gAgent.getRegion())
245 {
246 LLChat chat;
247 LLUIString notify = getString("entering_sim_range");
248 notify.setArg("[NAME]", entry->getName());
249 notify.setArg("[DISTANCE]", dist_string);
250 chat.mText = notify;
251 chat.mSourceType = CHAT_SOURCE_SYSTEM;
252 LLFloaterChat::addChat(chat, FALSE, FALSE);
253 entry->setNotified(RADAR_NOTIFIED_SIM);
254 }
255 }
256 }
257 }
258 if (notify_chat &&
259 (entry->getDistance() < chat_distance) &&
260 (entry->getNotified() < RADAR_NOTIFIED_CHAT))
261 {
262 LLChat chat;
263 LLUIString notify = getString("entering_chat_range");
264 notify.setArg("[NAME]", entry->getName());
265 notify.setArg("[DISTANCE]", dist_string);
266 chat.mText = notify;
267 chat.mSourceType = CHAT_SOURCE_SYSTEM;
268 LLFloaterChat::addChat(chat, FALSE, FALSE);
269 entry->setNotified(RADAR_NOTIFIED_CHAT);
270 }
271 }
326 272
327 chat.mText = notify; 273 // Only display avatars in range
328 chat.mSourceType = CHAT_SOURCE_SYSTEM; 274 if (entry->getDistance() <= range)
329 LLFloaterChat::addChat(chat, FALSE, FALSE); 275 {
330} 276 // Append typing string
277 std::string typing = "";
278 if (entry->getStatus() == RADAR_STATUS_TYPING)
279 {
280 typing = getString("is_typing")+ " ";
281 }
331 282
283 std::string mute_text = LLMuteList::getInstance()->isMuted(entry->getID()) ? getString("is_muted") : "";
284 element["id"] = entry->getID();
285 element["columns"][0]["column"] = "avatar_name";
286 element["columns"][0]["type"] = "text";
287// [RLVa:KB] - Alternate: Imprudence-1.2.0
288 //element["columns"][0]["value"] = typing + entry->getName() + " " + mute_text;
289 std::string fullname = (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) ?
290 gRlvHandler.getAnonym(fullname) :
291 typing + entry->getName() + " " + mute_text;
292 element["columns"][0]["value"] = fullname;
293// [/RLVa:KB]
294 element["columns"][1]["column"] = "avatar_distance";
295 element["columns"][1]["type"] = "text";
296 element["columns"][1]["value"] = dist_string+"m";
332 297
333void PanelRadar::removeFromChatList(LLUUID agent_id) 298 mRadarList->addElement(element, ADD_BOTTOM);
334{ 299 }
335 // Do we want to add a notice? 300 }
336 mChatAvatars.erase(agent_id);
337}
338 301
302 mRadarList->sortItems();
303 mRadarList->setScrollPos(scroll_pos);
304 if (mSelectedAvatar.notNull())
305 {
306 mRadarList->selectByID(mSelectedAvatar);
307 }
339 308
340bool PanelRadar::isTyping(LLUUID agent_id) 309 LLUIString av_count_string = (mRadarList->getItemCount() == 1) ? getString("avatars_in_singular") : getString("avatars_in_plural");
341{ 310 av_count_string.setArg("[COUNT]", llformat("%d", mRadarList->getItemCount()));
342 return (mTypingAvatars.count(agent_id) > 0); 311 childSetText("avatar_count", av_count_string.getString());
343}
344 312
313 updateButtonStates();
345 314
346void PanelRadar::addToTypingList(LLUUID agent_id) 315 LL_DEBUGS("Radar") << "mSelectedAvatar: " << mSelectedAvatar.asString() << LL_ENDL;
347{
348 mTypingAvatars.insert(agent_id);
349} 316}
350 317
351 318void PanelRadar::removeDeadEntries(const std::vector<LLUUID>& agent_ids)
352void PanelRadar::removeFromTypingList(LLUUID agent_id)
353{ 319{
354 mTypingAvatars.erase(agent_id); 320 if (agent_ids.empty())
355} 321 {
356 322 return;
323 }
357 324
358void PanelRadar::updateSimAvList(std::vector<LLUUID> agent_ids) 325 // TODO: this should really be a part of updateRadarDisplay
359{ 326 std::vector<LLUUID>::const_iterator vIt;
360 std::set<LLUUID>::iterator it; 327 std::map<LLUUID, PanelRadarEntry>::iterator mIt;
361 std::vector<LLUUID>::iterator result; 328 for (mIt = mAvatars.begin(); mIt != mAvatars.end();)
362 for (it = mSimAvatars.begin(); it != mSimAvatars.end(); )
363 { 329 {
364 result = find(agent_ids.begin(), agent_ids.end(), *it); 330 vIt = std::find(agent_ids.begin(), agent_ids.end(), mIt->first);
365 if (result == agent_ids.end()) 331 if (vIt == agent_ids.end())
366 { 332 {
367 mSimAvatars.erase(it++); 333 // Remember, removing from the map triggers the entry's default dtor
334 mAvatars.erase(mIt++);
368 } 335 }
369 else 336 else
370 { 337 {
371 it++; 338 mIt++;
372 } 339 }
373 } 340 }
374} 341}
375 342
376 343PanelRadarEntry* PanelRadar::getEntry(const LLUUID& agent_id)
377void PanelRadar::addToSimAvList(LLUUID agent_id, std::string distance)
378{ 344{
379 mSimAvatars.insert(agent_id); 345 if (agent_id.isNull())
380 LLChat chat; 346 {
381 347 return NULL;
382 LLUIString notify = getString("entering_sim_range"); 348 }
383 notify.setArg("[NAME]", getSelectedName(agent_id)); 349 else
384 notify.setArg("[DISTANCE]", distance); 350 {
385 351 std::map<LLUUID, PanelRadarEntry>::iterator mIt;
386 chat.mText = notify; 352 mIt = mAvatars.find(agent_id);
387 chat.mSourceType = CHAT_SOURCE_SYSTEM; 353 if (mIt != mAvatars.end())
388 LLFloaterChat::addChat(chat, FALSE, FALSE); 354 {
355 return &mIt->second;
356 }
357 return NULL;
358 }
389} 359}
390 360
391 361F32 PanelRadar::calculateDistance(const LLUUID& agent_id, LLVector3d agent_position)
392bool PanelRadar::isInSimAvList(LLUUID agent_id)
393{ 362{
394 if (mSimAvatars.count(agent_id) > 0) 363 // LL only sends height value up to 1024m, try to work around it if we can by using draw distance
364 if (agent_position.mdV[VZ] == 0.0f)
395 { 365 {
396 return true; 366 LLViewerObject *av_obj = gObjectList.findObject(agent_id);
367 if (av_obj != NULL && av_obj->isAvatar())
368 {
369 LLVOAvatar* avatarp = (LLVOAvatar*)av_obj;
370 if (avatarp != NULL)
371 {
372 agent_position = avatarp->getPositionGlobal();
373 }
374 }
397 } 375 }
398 return false; 376 return F32(dist_vec(agent_position, gAgent.getPositionGlobal())); // don't need F64 here (what dist_vec returns)
399} 377}
400 378
379bool PanelRadar::isKnown(const LLUUID& agent_id)
380{
381 return (mAvatars.count(agent_id) > 0);
382}
401 383
402void PanelRadar::updateButtonStates() 384void PanelRadar::updateButtonStates()
403{ 385{
404 bool enable = false; 386 static bool enable = false;
405 bool enable_unmute = false; 387 static bool enable_unmute = false;
406 bool enable_track = false; 388 static bool enable_track = false;
407 bool enable_estate = false; 389 static bool enable_estate = false;
408 bool enable_friend = false; 390 static bool enable_friend = false;
391
409 if (hasFocus()) 392 if (hasFocus())
410 { 393 {
411 enable = mSelectedAvatar.notNull() ? visibleItemsSelected() : false; 394 enable = mSelectedAvatar.notNull() ? visibleItemsSelected() : false;
@@ -426,11 +409,13 @@ void PanelRadar::updateButtonStates()
426 childSetEnabled("track_btn", enable_track); 409 childSetEnabled("track_btn", enable_track);
427 childSetEnabled("invite_btn", enable); 410 childSetEnabled("invite_btn", enable);
428 childSetEnabled("add_btn", enable); 411 childSetEnabled("add_btn", enable);
412 childSetEnabled("cam_btn", enable);
429 childSetEnabled("freeze_btn", enable_estate); 413 childSetEnabled("freeze_btn", enable_estate);
430 childSetEnabled("eject_btn", enable_estate); 414 childSetEnabled("eject_btn", enable_estate);
431 childSetEnabled("mute_btn", enable); 415 childSetEnabled("mute_btn", enable);
432 childSetEnabled("ar_btn", enable); 416 childSetEnabled("ar_btn", enable);
433 childSetEnabled("estate_eject_btn", enable_estate); 417 //childSetEnabled("estate_eject_btn", enable_estate);
418 childSetEnabled("estate_ban_btn", enable_estate);
434 419
435 if (enable_unmute) 420 if (enable_unmute)
436 { 421 {
@@ -536,21 +521,35 @@ LLUUID PanelRadar::getSelected()
536} 521}
537 522
538 523
539//static
540std::string PanelRadar::getSelectedName(const LLUUID &agent_id) 524std::string PanelRadar::getSelectedName(const LLUUID &agent_id)
541{ 525{
542 std::string agent_name; 526 std::string agent_name;
543 if(gCacheName->getFullName(agent_id, agent_name) && agent_name != " ") 527 if(!(gCacheName->getFullName(agent_id, agent_name) && agent_name != " "))
544 { 528 {
545 return agent_name; 529 agent_name = getString("unknown_avatar");
546 } 530 }
547 return LLStringUtil::null; 531 return agent_name;
532}
533
534void PanelRadar::sendAvatarPropertiesRequest(const LLUUID &agent_id)
535{
536 LL_DEBUGS("Radar") << "PanelRadar::sendAvatarPropertiesRequest()" << LL_ENDL;
537 LLMessageSystem *msg = gMessageSystem;
538
539 msg->newMessageFast(_PREHASH_AvatarPropertiesRequest);
540 msg->nextBlockFast( _PREHASH_AgentData);
541 msg->addUUIDFast( _PREHASH_AgentID, gAgent.getID() );
542 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
543 msg->addUUIDFast( _PREHASH_AvatarID, agent_id);
544 gAgent.sendReliableMessage();
548} 545}
549 546
550 547
551// 548//////////////////////////////////////////////////////////////
552// Avatar tab 549// //
553// 550// * AVATAR TAB* //
551// //
552//////////////////////////////////////////////////////////////
554 553
555// static 554// static
556void PanelRadar::onClickIM(void* user_data) 555void PanelRadar::onClickIM(void* user_data)
@@ -561,11 +560,10 @@ void PanelRadar::onClickIM(void* user_data)
561 { 560 {
562 LLUUID agent_id = item->getUUID(); 561 LLUUID agent_id = item->getUUID();
563 gIMMgr->setFloaterOpen(TRUE); 562 gIMMgr->setFloaterOpen(TRUE);
564 gIMMgr->addSession(getSelectedName(agent_id), IM_NOTHING_SPECIAL, agent_id); 563 gIMMgr->addSession(self->getSelectedName(agent_id), IM_NOTHING_SPECIAL, agent_id);
565 } 564 }
566} 565}
567 566
568
569// static 567// static
570void PanelRadar::onClickProfile(void* user_data) 568void PanelRadar::onClickProfile(void* user_data)
571{ 569{
@@ -578,7 +576,6 @@ void PanelRadar::onClickProfile(void* user_data)
578 } 576 }
579} 577}
580 578
581
582// static 579// static
583void PanelRadar::onClickOfferTeleport(void* user_data) 580void PanelRadar::onClickOfferTeleport(void* user_data)
584{ 581{
@@ -597,22 +594,22 @@ void PanelRadar::onClickTeleport(void* userdata)
597 PanelRadar *self = (PanelRadar*)userdata; 594 PanelRadar *self = (PanelRadar*)userdata;
598 LLScrollListItem *item = self->mRadarList->getFirstSelected(); 595 LLScrollListItem *item = self->mRadarList->getFirstSelected();
599 596
600 if ( item ) 597 if (item)
601 { 598 {
602 LLUUID agent_id = item->getUUID(); 599 LLUUID agent_id = item->getUUID();
603 std::string agent_name = getSelectedName(agent_id); 600 std::string agent_name = self->getSelectedName(agent_id);
604 if ( !agent_name.empty() ) 601 if (!agent_name.empty())
605 { 602 {
606 LLViewerObject *av_obj = gObjectList.findObject(agent_id); 603 LLViewerObject *av_obj = gObjectList.findObject(agent_id);
607 if (av_obj != NULL && av_obj->isAvatar()) 604 if (av_obj != NULL && av_obj->isAvatar())
608 { 605 {
609 LLVOAvatar* avatarp = (LLVOAvatar*)av_obj; 606 LLVOAvatar* avatarp = (LLVOAvatar*)av_obj;
610 if (avatarp != NULL) 607 if (avatarp != NULL)
611 { 608 {
612 LLVector3d pos = avatarp->getPositionGlobal(); 609 LLVector3d pos = avatarp->getPositionGlobal();
613 gAgent.teleportViaLocation(pos); 610 gAgent.teleportViaLocation(pos);
614 } 611 }
615 } 612 }
616 } 613 }
617 } 614 }
618} 615}
@@ -633,12 +630,11 @@ void PanelRadar::onClickTrack(void* user_data)
633 if (item != NULL) 630 if (item != NULL)
634 { 631 {
635 LLUUID agent_id = item->getUUID(); 632 LLUUID agent_id = item->getUUID();
636 LLTracker::trackAvatar(agent_id, getSelectedName(agent_id)); 633 LLTracker::trackAvatar(agent_id, self->getSelectedName(agent_id));
637 } 634 }
638 } 635 }
639} 636}
640 637
641
642// static 638// static
643void PanelRadar::onClickInvite(void* user_data) 639void PanelRadar::onClickInvite(void* user_data)
644{ 640{
@@ -658,7 +654,6 @@ void PanelRadar::onClickInvite(void* user_data)
658 } 654 }
659} 655}
660 656
661
662// static 657// static
663void PanelRadar::callback_invite_to_group(LLUUID group_id, void *user_data) 658void PanelRadar::callback_invite_to_group(LLUUID group_id, void *user_data)
664{ 659{
@@ -668,7 +663,6 @@ void PanelRadar::callback_invite_to_group(LLUUID group_id, void *user_data)
668 LLFloaterGroupInvite::showForGroup(group_id, &agent_ids); 663 LLFloaterGroupInvite::showForGroup(group_id, &agent_ids);
669} 664}
670 665
671
672// static 666// static
673void PanelRadar::onClickAddFriend(void* user_data) 667void PanelRadar::onClickAddFriend(void* user_data)
674{ 668{
@@ -677,70 +671,116 @@ void PanelRadar::onClickAddFriend(void* user_data)
677 if (item != NULL) 671 if (item != NULL)
678 { 672 {
679 LLUUID agent_id = item->getUUID(); 673 LLUUID agent_id = item->getUUID();
680 LLPanelFriends::requestFriendshipDialog(agent_id, getSelectedName(agent_id)); 674 LLPanelFriends::requestFriendshipDialog(agent_id, self->getSelectedName(agent_id));
681 } 675 }
682} 676}
683 677
684 678
679//////////////////////////////////////////////////////////////
680// //
681// * ESTATE TAB * //
682// //
683//////////////////////////////////////////////////////////////
685 684
686// 685// static
687// Estate tab 686void PanelRadar::onClickCam(void* user_data)
688// 687{
688 PanelRadar *self = (PanelRadar*)user_data;
689 self->lookAtAvatar(self->getSelected());
690}
689 691
692void PanelRadar::lookAtAvatar(const LLUUID& agent_id)
693{
694 LLViewerObject* voavatar = gObjectList.findObject(agent_id);
695 if (voavatar && voavatar->isAvatar())
696 {
697 gAgent.setFocusOnAvatar(FALSE, FALSE);
698 gAgent.changeCameraToThirdPerson();
699 gAgent.setFocusGlobal(voavatar->getPositionGlobal(), agent_id);
700 gAgent.setCameraPosAndFocusGlobal(voavatar->getPositionGlobal()
701 + LLVector3d(3.5,1.35,0.75) * voavatar->getRotation(),
702 voavatar->getPositionGlobal(),
703 agent_id );
704 }
705}
690 706
691//static 707//static
692bool PanelRadar::callbackFreeze(const LLSD& notification, const LLSD& response, PanelRadar *self) 708bool PanelRadar::callbackFreeze(const LLSD& notification, const LLSD& response, PanelRadar *self)
693{ 709{
694 S32 option = LLNotification::getSelectedOption(notification, response); 710 S32 option = LLNotification::getSelectedOption(notification, response);
695 if ( option == 0 ) 711 if (option == 0)
696 { 712 {
697 sendFreeze(self->mSelectedAvatar, true); 713 sendFreeze(self->mSelectedAvatar, true);
698 } 714 }
699 else if ( option == 1 ) 715 else if (option == 1)
700 { 716 {
701 sendFreeze(self->mSelectedAvatar, false); 717 sendFreeze(self->mSelectedAvatar, false);
702 } 718 }
703 return false; 719 return false;
704} 720}
705 721
706
707//static 722//static
708bool PanelRadar::callbackEject(const LLSD& notification, const LLSD& response, PanelRadar *self) 723bool PanelRadar::callbackEject(const LLSD& notification, const LLSD& response, PanelRadar *self)
709{ 724{
710 S32 option = LLNotification::getSelectedOption(notification, response); 725 S32 option = LLNotification::getSelectedOption(notification, response);
711 if ( option == 0 ) 726 if (option == 0)
712 { 727 {
713 sendEject(self->mSelectedAvatar, false); 728 sendEject(self->mSelectedAvatar, false);
714 } 729 }
715 else if ( option == 1 ) 730 else if (option == 1)
716 { 731 {
717 sendEject(self->mSelectedAvatar, true); 732 sendEject(self->mSelectedAvatar, true);
718 } 733 }
719 return false; 734 return false;
720} 735}
721 736
722
723//static 737//static
724bool PanelRadar::callbackEjectFromEstate(const LLSD& notification, const LLSD& response, PanelRadar *self) 738//bool PanelRadar::callbackEjectFromEstate(const LLSD& notification, const LLSD& response, PanelRadar *self)
739//{
740// S32 option = LLNotification::getSelectedOption(notification, response);
741// if (option == 0)
742// {
743// strings_t strings;
744// strings.push_back(self->getSelected().asString());
745// sendEstateOwnerMessage(gMessageSystem, "kickestate", LLFloaterRegionInfo::getLastInvoice(), strings);
746// }
747// return false;
748//}
749
750// static
751bool PanelRadar::callbackBanFromEstate(const LLSD& notification, const LLSD& response, PanelRadar *self)
725{ 752{
726 S32 option = LLNotification::getSelectedOption(notification, response); 753 S32 option = LLNotification::getSelectedOption(notification, response);
727 if ( option == 0 ) 754 if (option == 0)
728 { 755 {
729 cmdEstateEject(self->mSelectedAvatar); 756 LLPanelEstateInfo::sendEstateAccessDelta(ESTATE_ACCESS_BANNED_AGENT_ADD | ESTATE_ACCESS_ALLOWED_AGENT_REMOVE | ESTATE_ACCESS_NO_REPLY, self->getSelected());
730 } 757 }
731 else if ( option == 1 ) 758 else if (option == 1)
732 { 759 {
733 cmdEstateBan(self->mSelectedAvatar); 760 LLViewerRegion* regionp = gAgent.getRegion();
761 if (regionp)
762 {
763 U32 flags = ESTATE_ACCESS_BANNED_AGENT_ADD | ESTATE_ACCESS_ALLOWED_AGENT_REMOVE | ESTATE_ACCESS_NO_REPLY;
764 if (regionp->getOwner() == gAgent.getID() || gAgent.isGodlike())
765 {
766 flags |= ESTATE_ACCESS_APPLY_TO_ALL_ESTATES;
767 }
768 else if (regionp->isEstateManager())
769 {
770 flags |= ESTATE_ACCESS_APPLY_TO_MANAGED_ESTATES;
771 }
772 LLPanelEstateInfo::sendEstateAccessDelta(flags, self->getSelected());
773 }
734 } 774 }
735 return false; 775 return false;
736} 776}
737 777
738 778// static
739void PanelRadar::onClickFreeze(void *user_data) 779void PanelRadar::onClickFreeze(void *user_data)
740{ 780{
741 PanelRadar *self = (PanelRadar*)user_data; 781 PanelRadar *self = (PanelRadar*)user_data;
742 LLSD args; 782 LLSD args;
743 args["AVATAR_NAME"] = getSelectedName(self->mSelectedAvatar); 783 args["AVATAR_NAME"] = self->getSelectedName(self->mSelectedAvatar);
744 LLNotifications::instance().add("FreezeAvatarFullname", 784 LLNotifications::instance().add("FreezeAvatarFullname",
745 args, 785 args,
746 LLSD(), 786 LLSD(),
@@ -748,20 +788,28 @@ void PanelRadar::onClickFreeze(void *user_data)
748} 788}
749 789
750 790
751//static 791// static
752void PanelRadar::onClickEject(void *user_data) 792void PanelRadar::onClickUnfreeze(void *user_data)
753{ 793{
754 PanelRadar *self = (PanelRadar*)user_data; 794 PanelRadar *self = (PanelRadar*)user_data;
755 LLSD args; 795 sendFreeze(self->getSelected(), false);
756 args["AVATAR_NAME"] = getSelectedName(self->mSelectedAvatar);
757 LLNotifications::instance().add("EjectAvatarFullname",
758 args,
759 LLSD(),
760 boost::bind(&callbackEject, _1, _2, self));
761} 796}
762 797
763 798
764//static 799//static
800//void PanelRadar::onClickEjectFromEstate(void *user_data)
801//{
802// PanelRadar *self = (PanelRadar*)user_data;
803// LLSD args;
804// args["AVATAR_NAME"] = self->getSelectedName(self->mSelectedAvatar);
805// LLNotifications::instance().add("EjectAvatarFullnameNoBan",
806// args,
807// LLSD(),
808// boost::bind(&callbackEjectFromEstate, _1, _2, self));
809//}
810
811
812//static
765void PanelRadar::onClickMute(void *user_data) 813void PanelRadar::onClickMute(void *user_data)
766{ 814{
767 PanelRadar *self = (PanelRadar*)user_data; 815 PanelRadar *self = (PanelRadar*)user_data;
@@ -769,7 +817,7 @@ void PanelRadar::onClickMute(void *user_data)
769 if (item != NULL) 817 if (item != NULL)
770 { 818 {
771 LLUUID agent_id = item->getUUID(); 819 LLUUID agent_id = item->getUUID();
772 std::string agent_name = getSelectedName(agent_id); 820 std::string agent_name = self->getSelectedName(agent_id);
773 if (LLMuteList::getInstance()->isMuted(agent_id)) 821 if (LLMuteList::getInstance()->isMuted(agent_id))
774 { 822 {
775 //LLMute mute(agent_id, agent_name, LLMute::AGENT); 823 //LLMute mute(agent_id, agent_name, LLMute::AGENT);
@@ -793,7 +841,7 @@ void PanelRadar::onClickUnmute(void *user_data)
793 if (item != NULL) 841 if (item != NULL)
794 { 842 {
795 LLUUID agent_id = item->getUUID(); 843 LLUUID agent_id = item->getUUID();
796 std::string agent_name = getSelectedName(agent_id); 844 std::string agent_name = self->getSelectedName(agent_id);
797 if (LLMuteList::getInstance()->isMuted(agent_id)) 845 if (LLMuteList::getInstance()->isMuted(agent_id))
798 { 846 {
799 LLMute mute(agent_id, agent_name, LLMute::AGENT); 847 LLMute mute(agent_id, agent_name, LLMute::AGENT);
@@ -810,15 +858,15 @@ void PanelRadar::onClickUnmute(void *user_data)
810 858
811 859
812//static 860//static
813void PanelRadar::onClickEjectFromEstate(void *user_data) 861void PanelRadar::onClickEject(void *user_data)
814{ 862{
815 PanelRadar *self = (PanelRadar*)user_data; 863 PanelRadar *self = (PanelRadar*)user_data;
816 LLSD args; 864 LLSD args;
817 args["EVIL_USER"] = getSelectedName(self->mSelectedAvatar); 865 args["EVIL_USER"] = self->getSelectedName(self->mSelectedAvatar);
818 LLNotifications::instance().add("EstateKickUser", 866 LLNotifications::instance().add("EstateKickUser",
819 args, 867 args,
820 LLSD(), 868 LLSD(),
821 boost::bind(&callbackEjectFromEstate, _1, _2, self)); 869 boost::bind(&callbackEject, _1, _2, self));
822} 870}
823 871
824 872
@@ -835,6 +883,16 @@ void PanelRadar::onClickAR(void *user_data)
835} 883}
836 884
837 885
886//static
887void PanelRadar::onClickBanFromEstate(void *user_data)
888{
889 PanelRadar *self = (PanelRadar*)user_data;
890 LLSD args;
891 args["ALL_ESTATES"] = "all estates";
892 LLNotifications::instance().add("EstateBannedAgentAdd", args, LLSD(), boost::bind(&callbackBanFromEstate, _1, _2, self));
893}
894
895
838// static 896// static
839void PanelRadar::cmdEstateEject(const LLUUID &avatar) 897void PanelRadar::cmdEstateEject(const LLUUID &avatar)
840{ 898{
@@ -971,3 +1029,37 @@ void PanelRadar::sendEstateBan(const LLUUID& agent)
971 1029
972 gAgent.sendReliableMessage(); 1030 gAgent.sendReliableMessage();
973} 1031}
1032
1033//typedef std::vector<std::string> strings_t;
1034//static void sendEstateOwnerMessage(
1035// LLMessageSystem* msg,
1036// const std::string& request,
1037// const LLUUID& invoice,
1038// const strings_t& strings)
1039//{
1040// llinfos << "Sending estate request '" << request << "'" << llendl;
1041// msg->newMessage("EstateOwnerMessage");
1042// msg->nextBlockFast(_PREHASH_AgentData);
1043// msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
1044// msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
1045// msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); //not used
1046// msg->nextBlock("MethodData");
1047// msg->addString("Method", request);
1048// msg->addUUID("Invoice", invoice);
1049// if(strings.empty())
1050// {
1051// msg->nextBlock("ParamList");
1052// msg->addString("Parameter", NULL);
1053// }
1054// else
1055// {
1056// strings_t::const_iterator it = strings.begin();
1057// strings_t::const_iterator end = strings.end();
1058// for(; it != end; ++it)
1059// {
1060// msg->nextBlock("ParamList");
1061// msg->addString("Parameter", *it);
1062// }
1063// }
1064// msg->sendReliable(gAgent.getRegion()->getHost());
1065//}
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 @@
33#include "llpanel.h" 33#include "llpanel.h"
34#include "llscrolllistctrl.h" 34#include "llscrolllistctrl.h"
35 35
36class PanelRadarEntry;
36 37
37class PanelRadar : public LLPanel 38class PanelRadar : public LLPanel
38{ 39{
@@ -42,44 +43,44 @@ public:
42 43
43 BOOL postBuild(); 44 BOOL postBuild();
44 45
45 // returns true if agent_id belongs to an Imprudence developer 46 // Returns true if agent_id belongs to an Imprudence developer
46 static bool isImpDev(LLUUID agent_id); 47 bool isImpDev(const LLUUID& agent_id);
47 48 // Change the camera focus to an avatar
49 void lookAtAvatar(const LLUUID& agent_id);
50
51 // Returns UUID of currently selected avatar
48 LLUUID getSelected(); 52 LLUUID getSelected();
49 53
50 void addToTypingList(LLUUID agent_id); 54 // Updates the radar button states
51 void removeFromTypingList(LLUUID agent_id);
52
53 void updateButtonStates(); 55 void updateButtonStates();
54 void populateRadar(); 56 // Update the list of known avatars
57 void updateRadarInfo();
58 // Update the radar UI. Call updateRadarInfo first
59 void updateRadarDisplay();
60
61 // Returns PanelRadarEntry* if key is found, NULL if not
62 PanelRadarEntry* getEntry(const LLUUID& agent_id);
63 // Returns true if avatar is in the radar's list
64 bool isKnown(const LLUUID& agent_id);
55 65
56private: 66private:
57 67
58 // TODO: move all this info into its own object. It's stupid 68 std::map<LLUUID, PanelRadarEntry> mAvatars;
59 // and bug-prone to keep it all in separate containers, but 69
60 // I want to get this out for 1.2 -- McCabe 70 // Returns your distance from an avatar's position
61 std::set<LLUUID> mChatAvatars; 71 F32 calculateDistance(const LLUUID& agent_id, LLVector3d agent_position);
62 std::set<LLUUID> mTypingAvatars; 72 // Removes avatar IDs no longer known to the viewer
63 std::set<LLUUID> mSimAvatars; 73 void removeDeadEntries(const std::vector<LLUUID>& agent_ids);
64 74
65 LLScrollListCtrl* mRadarList; 75 LLScrollListCtrl* mRadarList;
66 LLUUID mSelectedAvatar; 76 LLUUID mSelectedAvatar;
67 77
68 void updateChatList(std::vector<LLUUID> agent_ids);
69 bool isInChatList(LLUUID agent_id);
70 void addToChatList(LLUUID agent_id, std::string distance);
71 void removeFromChatList(LLUUID agent_id);
72
73 bool isInSimAvList(LLUUID agent_id);
74 void addToSimAvList(LLUUID agent_id, std::string distance);
75 void updateSimAvList(std::vector<LLUUID> agent_ids);
76
77 bool isTyping(LLUUID agent_id);
78
79 bool visibleItemsSelected() const; 78 bool visibleItemsSelected() const;
80 bool isKickable(const LLUUID &agent_id); 79 bool isKickable(const LLUUID &agent_id);
81 80
82 static std::string getSelectedName(const LLUUID &agent_id); 81 std::string getSelectedName(const LLUUID &agent_id);
82
83 void sendAvatarPropertiesRequest(const LLUUID &agent_id);
83 84
84 static void onUseRadarList(LLUICtrl* ctrl, void* user_data); 85 static void onUseRadarList(LLUICtrl* ctrl, void* user_data);
85 static void onRangeChange(LLFocusableElement* focus, void* user_data); 86 static void onRangeChange(LLFocusableElement* focus, void* user_data);
@@ -93,25 +94,28 @@ private:
93 static void onClickInvite(void* user_data); 94 static void onClickInvite(void* user_data);
94 static void callback_invite_to_group(LLUUID group_id, void *user_data); 95 static void callback_invite_to_group(LLUUID group_id, void *user_data);
95 96
97 static void onClickCam(void* user_data);
96 static void onClickFreeze(void *user_data); 98 static void onClickFreeze(void *user_data);
99 static void onClickUnfreeze(void *user_data);
97 static void onClickEject(void *user_data); 100 static void onClickEject(void *user_data);
98 static void onClickMute(void *user_data); 101 static void onClickMute(void *user_data);
99 static void onClickUnmute(void *user_data); 102 static void onClickUnmute(void *user_data);
100 static void onClickAR(void *user_data); 103 static void onClickAR(void *user_data);
101 static void onClickEjectFromEstate(void *user_data); 104 //static void onClickEjectFromEstate(void *user_data); Not working yet
105 static void onClickBanFromEstate(void *user_data);
102 106
103 static void callbackAR(void *user_data); 107 static void callbackAR(void *user_data);
104 static bool callbackFreeze(const LLSD& notification, const LLSD& response, PanelRadar *self); 108 static bool callbackFreeze(const LLSD& notification, const LLSD& response, PanelRadar *self);
105 static bool callbackEject(const LLSD& notification, const LLSD& response, PanelRadar *self); 109 static bool callbackEject(const LLSD& notification, const LLSD& response, PanelRadar *self);
106 static bool callbackEjectFromEstate(const LLSD& notification, const LLSD& response, PanelRadar *self); 110 //static bool callbackEjectFromEstate(const LLSD& notification, const LLSD& response, PanelRadar *self);
111 static bool callbackBanFromEstate(const LLSD& notification, const LLSD& response, PanelRadar *self);
107 112
108 static void sendFreeze(const LLUUID &avatar, bool); 113 static void sendFreeze(const LLUUID& avatar, bool freeze);
109 static void sendEject(const LLUUID &avatar, bool); 114 static void sendEject(const LLUUID& avatar, bool ban);
110 static void cmdEstateEject(const LLUUID &avatar); 115 static void cmdEstateEject(const LLUUID &avatar);
111 static void cmdEstateBan(const LLUUID &avatar); 116 static void cmdEstateBan(const LLUUID &avatar);
112 static void sendEstateBan(const LLUUID& agent); 117 static void sendEstateBan(const LLUUID& agent);
113 static void sendEstateMessage(const char* request, const LLUUID &target); 118 static void sendEstateMessage(const char* request, const LLUUID &target);
114
115}; 119};
116 120
117 121
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 @@
1/**
2 * @file panelradarentry.cpp
3 * @brief PanelRadarEntry class (container for nearby agents)
4 *
5 * Copyright (c) 2010, McCabe Maxsted
6 *
7 * The source code in this file ("Source Code") is provided to you
8 * under the terms of the GNU General Public License, version 2.0
9 * ("GPL"). Terms of the GPL can be found in doc/GPL-license.txt in
10 * this distribution, or online at
11 * http://secondlifegrid.net/programs/open_source/licensing/gplv2
12 *
13 * There are special exceptions to the terms and conditions of the GPL as
14 * it is applied to this Source Code. View the full text of the exception
15 * in the file doc/FLOSS-exception.txt in this software distribution, or
16 * online at
17 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL SOURCE CODE IS PROVIDED "AS IS." THE AUTHOR MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#include "llviewerprecompiledheaders.h"
29
30#include "panelradarentry.h"
31
32const F32 RADAR_STATUS_TIMEOUT = 30.0f; // 30 seconds seems to be a good timeout
33
34PanelRadarEntry::PanelRadarEntry(const LLUUID& agent_id, const std::string& agent_name, const F32& distance, const LLVector3d& position, const RADAR_STATUS& status, const RADAR_NOTIFIED& notified) :
35 mID(agent_id),
36 mName(agent_name),
37 mDistance(distance),
38 mPosition(position),
39 mStatus(status),
40 mNotified(notified),
41 mStatusTimer()
42{
43 mStatusTimer.setTimerExpirySec(RADAR_STATUS_TIMEOUT);
44}
45
46void PanelRadarEntry::setName(const std::string& name)
47{
48 mName = name;
49}
50
51void PanelRadarEntry::setDistance(const F32& distance)
52{
53 mDistance = distance;
54}
55
56void PanelRadarEntry::setPosition(const LLVector3d& position)
57{
58 mPosition = position;
59}
60
61void PanelRadarEntry::setStatus(const RADAR_STATUS& status)
62{
63 if (status <= RADAR_STATUS_AWAY)
64 {
65 mStatus = status;
66
67 if (mStatus != RADAR_STATUS_NONE || mStatusTimer.hasExpired())
68 {
69 mStatusTimer.start();
70 mStatusTimer.setTimerExpirySec(RADAR_STATUS_TIMEOUT);
71 }
72 else
73 {
74 mStatusTimer.stop();
75 }
76 }
77}
78
79void PanelRadarEntry::setNotified(const RADAR_NOTIFIED& notified)
80{
81 if (notified <= RADAR_NOTIFIED_SIM)
82 {
83 mNotified = notified;
84 }
85}
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 @@
1/**
2 * @file panelradarentry.h
3 * @brief PanelRadarEntry class (container for nearby agents)
4 *
5 * Copyright (c) 2010, McCabe Maxsted
6 *
7 * The source code in this file ("Source Code") is provided to you
8 * under the terms of the GNU General Public License, version 2.0
9 * ("GPL"). Terms of the GPL can be found in doc/GPL-license.txt in
10 * this distribution, or online at
11 * http://secondlifegrid.net/programs/open_source/licensing/gplv2
12 *
13 * There are special exceptions to the terms and conditions of the GPL as
14 * it is applied to this Source Code. View the full text of the exception
15 * in the file doc/FLOSS-exception.txt in this software distribution, or
16 * online at
17 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL SOURCE CODE IS PROVIDED "AS IS." THE AUTHOR MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28
29#ifndef PANELRADARENTRY_H
30#define PANELRADARENTRY_H
31
32
33#include "llframetimer.h"
34
35enum RADAR_STATUS
36{
37 RADAR_STATUS_NONE,
38 RADAR_STATUS_TYPING,
39 RADAR_STATUS_EMITTING_SOUNDS,
40 RADAR_STATUS_EMITTING_PARTICLES,
41 RADAR_STATUS_FLYING,
42 RADAR_STATUS_BUSY,
43 RADAR_STATUS_AWAY
44};
45
46enum RADAR_NOTIFIED
47{
48 RADAR_NOTIFIED_NONE,
49 RADAR_NOTIFIED_SIM,
50 RADAR_NOTIFIED_CHAT
51};
52
53
54class PanelRadarEntry
55{
56public:
57 PanelRadarEntry(const LLUUID& agent_id, const std::string& agent_name, const F32& distance, const LLVector3d& position, const RADAR_STATUS& status, const RADAR_NOTIFIED& notified);
58
59 LLUUID getID() { return mID; }
60 std::string getName() { return mName; }
61 F32 getDistance() { return mDistance; }
62 LLVector3d getPosition() { return mPosition; }
63 RADAR_STATUS getStatus() { return mStatus; }
64 RADAR_NOTIFIED getNotified() { return mNotified; }
65 LLFrameTimer getStatusTimer(){ return mStatusTimer; }
66
67 void setName(const std::string& name);
68 void setDistance(const F32& distance);
69 void setPosition(const LLVector3d& position);
70 void setStatus(const RADAR_STATUS& status);
71 void setNotified(const RADAR_NOTIFIED& notified);
72
73private:
74 LLUUID mID;
75 std::string mName;
76 F32 mDistance;
77 LLVector3d mPosition;
78 RADAR_STATUS mStatus;
79 RADAR_NOTIFIED mNotified;
80 LLFrameTimer mStatusTimer;
81};
82
83#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 @@
22 [NAME] has entered the sim ([DISTANCE]m) 22 [NAME] has entered the sim ([DISTANCE]m)
23 </string> 23 </string>
24 <string name="avatars_in_singular"> 24 <string name="avatars_in_singular">
25 avatar in 25 [COUNT] avatar in
26 </string> 26 </string>
27 <string name="avatars_in_plural"> 27 <string name="avatars_in_plural">
28 avatars in 28 [COUNT] avatars in
29 </string>
30 <string name="unknown_avatar">
31 (Unknown)
29 </string> 32 </string>
30 33
31 <text name="lblAvatarCount" 34 <text name="avatar_count"
32 bottom="-20" left="10" height="16" width="220" 35 bottom="-20" left="10" height="16" width="220"
33 h_pad="0" halign="left" v_pad="0" follows="left|top" 36 h_pad="0" halign="left" v_pad="0" follows="left|top"
34 bg_visible="false" border_drop_shadow_visible="false" 37 bg_visible="false" border_drop_shadow_visible="false"
35 border_visible="false" drop_shadow_visible="true" 38 border_visible="false" drop_shadow_visible="true"
36 font="SansSerifSmall" mouse_opaque="true"> 39 font="SansSerifSmall" mouse_opaque="true">
37 0 40 0 avatars in
38 </text>
39
40 <text name="avatars_in"
41 bottom="-20" left="27" height="16" width="220"
42 h_pad="0" halign="left" v_pad="0"
43 bg_visible="false" border_drop_shadow_visible="false"
44 border_visible="false" drop_shadow_visible="true" follows="left|top"
45 font="SansSerifSmall" mouse_opaque="true" >
46 avatars in
47 </text> 41 </text>
48 42
49 <slider name="near_me_range" label="" control_name="NearMeRange" 43 <slider name="near_me_range" label="" control_name="NearMeRange"
@@ -111,9 +105,13 @@
111 bottom="-160" left="1" height="160" width="198" 105 bottom="-160" left="1" height="160" width="198"
112 follows="left|top|right|bottom" 106 follows="left|top|right|bottom"
113 border="false" mouse_opaque="true"> 107 border="false" mouse_opaque="true">
108
109 <button name="cam_btn" label="Cam To"
110 bottom="-22" left="-85" height="20" width="80"
111 follows="top|right" tool_tip="" />
114 112
115 <button name="freeze_btn" label="Freeze..." 113 <button name="freeze_btn" label="Freeze..."
116 bottom="-22" left="-85" height="20" width="80" 114 bottom_delta="-22" left="-85" height="20" width="80"
117 follows="top|right" tool_tip="" /> 115 follows="top|right" tool_tip="" />
118 116
119 <button name="eject_btn" label="Eject..." 117 <button name="eject_btn" label="Eject..."
@@ -132,7 +130,11 @@
132 bottom_delta="-22" left_delta="0" height="20" width="80" 130 bottom_delta="-22" left_delta="0" height="20" width="80"
133 follows="top|right" tool_tip="" /> 131 follows="top|right" tool_tip="" />
134 132
135 <button name="estate_eject_btn" label="Kick..." 133 <!--<button name="estate_eject_btn" label="Kick..."
134 bottom_delta="-22" left_delta="0" height="20" width="80"
135 follows="top|right" tool_tip="" />-->
136
137 <button name="estate_ban_btn" label="Ban..."
136 bottom_delta="-22" left_delta="0" height="20" width="80" 138 bottom_delta="-22" left_delta="0" height="20" width="80"
137 follows="top|right" tool_tip="" /> 139 follows="top|right" tool_tip="" />
138 140