diff options
Diffstat (limited to '')
-rw-r--r-- | linden/indra/newview/llpanelpick.cpp | 513 |
1 files changed, 513 insertions, 0 deletions
diff --git a/linden/indra/newview/llpanelpick.cpp b/linden/indra/newview/llpanelpick.cpp new file mode 100644 index 0000000..4c9d5c3 --- /dev/null +++ b/linden/indra/newview/llpanelpick.cpp | |||
@@ -0,0 +1,513 @@ | |||
1 | /** | ||
2 | * @file llpanelpick.cpp | ||
3 | * @brief LLPanelPick class implementation | ||
4 | * | ||
5 | * Copyright (c) 2004-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
8 | * to you under the terms of the GNU General Public License, version 2.0 | ||
9 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
10 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
11 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
12 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
13 | * | ||
14 | * There are special exceptions to the terms and conditions of the GPL as | ||
15 | * it is applied to this Source Code. View the full text of the exception | ||
16 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
17 | * online at http://secondlife.com/developers/opensource/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 LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
24 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
25 | * COMPLETENESS OR PERFORMANCE. | ||
26 | */ | ||
27 | |||
28 | // Display of a "Top Pick" used both for the global top picks in the | ||
29 | // Find directory, and also for each individual user's picks in their | ||
30 | // profile. | ||
31 | |||
32 | #include "llviewerprecompiledheaders.h" | ||
33 | |||
34 | #include "llpanelpick.h" | ||
35 | |||
36 | #include "lldir.h" | ||
37 | #include "llparcel.h" | ||
38 | #include "message.h" | ||
39 | |||
40 | #include "llagent.h" | ||
41 | #include "llbutton.h" | ||
42 | #include "llcheckboxctrl.h" | ||
43 | #include "llviewercontrol.h" | ||
44 | #include "lllineeditor.h" | ||
45 | #include "lltabcontainervertical.h" | ||
46 | #include "lltextbox.h" | ||
47 | #include "llviewertexteditor.h" | ||
48 | #include "lltexturectrl.h" | ||
49 | #include "lluiconstants.h" | ||
50 | #include "llvieweruictrlfactory.h" | ||
51 | #include "llviewerparcelmgr.h" | ||
52 | #include "llworldmap.h" | ||
53 | #include "llfloaterworldmap.h" | ||
54 | #include "llviewerregion.h" | ||
55 | #include "llviewerwindow.h" | ||
56 | |||
57 | //static | ||
58 | LLLinkedList<LLPanelPick> LLPanelPick::sAllPanels; | ||
59 | |||
60 | LLPanelPick::LLPanelPick(BOOL top_pick) | ||
61 | : LLPanel("Top Picks Panel"), | ||
62 | mTopPick(top_pick), | ||
63 | mPickID(), | ||
64 | mCreatorID(), | ||
65 | mParcelID(), | ||
66 | mDataRequested(FALSE), | ||
67 | mDataReceived(FALSE), | ||
68 | mPosGlobal(), | ||
69 | mSnapshotCtrl(NULL), | ||
70 | mNameEditor(NULL), | ||
71 | mDescEditor(NULL), | ||
72 | mLocationEditor(NULL), | ||
73 | mTeleportBtn(NULL), | ||
74 | mMapBtn(NULL), | ||
75 | //mLandmarkBtn(NULL), | ||
76 | mSortOrderText(NULL), | ||
77 | mSortOrderEditor(NULL), | ||
78 | mEnabledCheck(NULL), | ||
79 | mSetBtn(NULL) | ||
80 | { | ||
81 | sAllPanels.addData(this); | ||
82 | |||
83 | std::string pick_def_file; | ||
84 | if (top_pick) | ||
85 | { | ||
86 | gUICtrlFactory->buildPanel(this, "panel_top_pick.xml"); | ||
87 | } | ||
88 | else | ||
89 | { | ||
90 | gUICtrlFactory->buildPanel(this, "panel_avatar_pick.xml"); | ||
91 | } | ||
92 | } | ||
93 | |||
94 | |||
95 | LLPanelPick::~LLPanelPick() | ||
96 | { | ||
97 | sAllPanels.removeData(this); | ||
98 | } | ||
99 | |||
100 | |||
101 | void LLPanelPick::reset() | ||
102 | { | ||
103 | mPickID.setNull(); | ||
104 | mCreatorID.setNull(); | ||
105 | mParcelID.setNull(); | ||
106 | |||
107 | // Don't request data, this isn't valid | ||
108 | mDataRequested = TRUE; | ||
109 | mDataReceived = FALSE; | ||
110 | |||
111 | mPosGlobal.clearVec(); | ||
112 | |||
113 | clearCtrls(); | ||
114 | } | ||
115 | |||
116 | |||
117 | BOOL LLPanelPick::postBuild() | ||
118 | { | ||
119 | mSnapshotCtrl = LLViewerUICtrlFactory::getTexturePickerByName(this, "snapshot_ctrl"); | ||
120 | mSnapshotCtrl->setCommitCallback(onCommitAny); | ||
121 | mSnapshotCtrl->setCallbackUserData(this); | ||
122 | |||
123 | mNameEditor = LLViewerUICtrlFactory::getLineEditorByName(this, "given_name_editor"); | ||
124 | mNameEditor->setCommitOnFocusLost(TRUE); | ||
125 | mNameEditor->setCommitCallback(onCommitAny); | ||
126 | mNameEditor->setCallbackUserData(this); | ||
127 | |||
128 | mDescEditor = LLUICtrlFactory::getTextEditorByName(this, "desc_editor"); | ||
129 | mDescEditor->setCommitOnFocusLost(TRUE); | ||
130 | mDescEditor->setCommitCallback(onCommitAny); | ||
131 | mDescEditor->setCallbackUserData(this); | ||
132 | mDescEditor->setTabToNextField(TRUE); | ||
133 | |||
134 | mLocationEditor = LLViewerUICtrlFactory::getLineEditorByName(this, "location_editor"); | ||
135 | |||
136 | mSetBtn = LLViewerUICtrlFactory::getButtonByName(this, "set_location_btn"); | ||
137 | mSetBtn->setClickedCallback(onClickSet); | ||
138 | mSetBtn->setCallbackUserData(this); | ||
139 | |||
140 | mTeleportBtn = LLViewerUICtrlFactory::getButtonByName(this, "pick_teleport_btn"); | ||
141 | mTeleportBtn->setClickedCallback(onClickTeleport); | ||
142 | mTeleportBtn->setCallbackUserData(this); | ||
143 | |||
144 | mMapBtn = LLViewerUICtrlFactory::getButtonByName(this, "pick_map_btn"); | ||
145 | mMapBtn->setClickedCallback(onClickMap); | ||
146 | mMapBtn->setCallbackUserData(this); | ||
147 | |||
148 | mSortOrderText = LLViewerUICtrlFactory::getTextBoxByName(this, "sort_order_text"); | ||
149 | |||
150 | mSortOrderEditor = LLViewerUICtrlFactory::getLineEditorByName(this, "sort_order_editor"); | ||
151 | mSortOrderEditor->setPrevalidate(LLLineEditor::prevalidateInt); | ||
152 | mSortOrderEditor->setCommitOnFocusLost(TRUE); | ||
153 | mSortOrderEditor->setCommitCallback(onCommitAny); | ||
154 | mSortOrderEditor->setCallbackUserData(this); | ||
155 | |||
156 | mEnabledCheck = LLViewerUICtrlFactory::getCheckBoxByName(this, "enabled_check"); | ||
157 | mEnabledCheck->setCommitCallback(onCommitAny); | ||
158 | mEnabledCheck->setCallbackUserData(this); | ||
159 | |||
160 | return TRUE; | ||
161 | } | ||
162 | |||
163 | |||
164 | // Fill in some reasonable defaults for a new pick. | ||
165 | void LLPanelPick::initNewPick() | ||
166 | { | ||
167 | mPickID.generate(); | ||
168 | |||
169 | mCreatorID = gAgent.getID(); | ||
170 | |||
171 | mPosGlobal = gAgent.getPositionGlobal(); | ||
172 | |||
173 | // Try to fill in the current parcel | ||
174 | LLParcel* parcel = gParcelMgr->getAgentParcel(); | ||
175 | if (parcel) | ||
176 | { | ||
177 | mNameEditor->setText(parcel->getName()); | ||
178 | mDescEditor->setText(parcel->getDesc()); | ||
179 | mSnapshotCtrl->setImageAssetID(parcel->getSnapshotID()); | ||
180 | } | ||
181 | |||
182 | // Commit to the database, since we've got "new" values. | ||
183 | sendPickInfoUpdate(); | ||
184 | } | ||
185 | |||
186 | |||
187 | void LLPanelPick::setPickID(const LLUUID& id) | ||
188 | { | ||
189 | mPickID = id; | ||
190 | } | ||
191 | |||
192 | |||
193 | // Schedules the panel to request data | ||
194 | // from the server next time it is drawn. | ||
195 | void LLPanelPick::markForServerRequest() | ||
196 | { | ||
197 | mDataRequested = FALSE; | ||
198 | mDataReceived = FALSE; | ||
199 | } | ||
200 | |||
201 | |||
202 | std::string LLPanelPick::getPickName() | ||
203 | { | ||
204 | return mNameEditor->getText(); | ||
205 | } | ||
206 | |||
207 | |||
208 | void LLPanelPick::sendPickInfoRequest() | ||
209 | { | ||
210 | LLMessageSystem *msg = gMessageSystem; | ||
211 | |||
212 | msg->newMessage("PickInfoRequest"); | ||
213 | msg->nextBlock("AgentData"); | ||
214 | msg->addUUID("AgentID", gAgent.getID() ); | ||
215 | msg->addUUID("SessionID", gAgent.getSessionID()); | ||
216 | msg->nextBlock("Data"); | ||
217 | msg->addUUID("PickID", mPickID); | ||
218 | gAgent.sendReliableMessage(); | ||
219 | |||
220 | mDataRequested = TRUE; | ||
221 | } | ||
222 | |||
223 | |||
224 | void LLPanelPick::sendPickInfoUpdate() | ||
225 | { | ||
226 | // If we don't have a pick id yet, we'll need to generate one, | ||
227 | // otherwise we'll keep overwriting pick_id 00000 in the database. | ||
228 | if (mPickID.isNull()) | ||
229 | { | ||
230 | mPickID.generate(); | ||
231 | } | ||
232 | |||
233 | LLMessageSystem* msg = gMessageSystem; | ||
234 | |||
235 | msg->newMessage("PickInfoUpdate"); | ||
236 | msg->nextBlock("AgentData"); | ||
237 | msg->addUUID("AgentID", gAgent.getID()); | ||
238 | msg->addUUID("SessionID", gAgent.getSessionID()); | ||
239 | msg->nextBlock("Data"); | ||
240 | msg->addUUID("PickID", mPickID); | ||
241 | msg->addUUID("CreatorID", mCreatorID); | ||
242 | msg->addBOOL("TopPick", mTopPick); | ||
243 | // fills in on simulator if null | ||
244 | msg->addUUID("ParcelID", mParcelID); | ||
245 | msg->addString("Name", mNameEditor->getText()); | ||
246 | msg->addString("Desc", mDescEditor->getText()); | ||
247 | msg->addUUID("SnapshotID", mSnapshotCtrl->getImageAssetID()); | ||
248 | msg->addVector3d("PosGlobal", mPosGlobal); | ||
249 | |||
250 | // Only top picks have a sort order | ||
251 | S32 sort_order; | ||
252 | if (mTopPick) | ||
253 | { | ||
254 | sort_order = atoi(mSortOrderEditor->getText().c_str()); | ||
255 | } | ||
256 | else | ||
257 | { | ||
258 | sort_order = 0; | ||
259 | } | ||
260 | msg->addS32("SortOrder", sort_order); | ||
261 | msg->addBOOL("Enabled", mEnabledCheck->get()); | ||
262 | gAgent.sendReliableMessage(); | ||
263 | } | ||
264 | |||
265 | |||
266 | //static | ||
267 | void LLPanelPick::processPickInfoReply(LLMessageSystem *msg, void **) | ||
268 | { | ||
269 | // Extract the agent id and verify the message is for this | ||
270 | // client. | ||
271 | LLUUID agent_id; | ||
272 | msg->getUUID("AgentData", "AgentID", agent_id ); | ||
273 | if (agent_id != gAgent.getID()) | ||
274 | { | ||
275 | llwarns << "Agent ID mismatch in processPickInfoReply" | ||
276 | << llendl; | ||
277 | return; | ||
278 | } | ||
279 | |||
280 | LLUUID pick_id; | ||
281 | msg->getUUID("Data", "PickID", pick_id); | ||
282 | |||
283 | LLUUID creator_id; | ||
284 | msg->getUUID("Data", "CreatorID", creator_id); | ||
285 | |||
286 | BOOL top_pick; | ||
287 | msg->getBOOL("Data", "TopPick", top_pick); | ||
288 | |||
289 | LLUUID parcel_id; | ||
290 | msg->getUUID("Data", "ParcelID", parcel_id); | ||
291 | |||
292 | char name[DB_PARCEL_NAME_SIZE]; | ||
293 | msg->getString("Data", "Name", DB_PARCEL_NAME_SIZE, name); | ||
294 | |||
295 | char desc[DB_PICK_DESC_SIZE]; | ||
296 | msg->getString("Data", "Desc", DB_PICK_DESC_SIZE, desc); | ||
297 | |||
298 | LLUUID snapshot_id; | ||
299 | msg->getUUID("Data", "SnapshotID", snapshot_id); | ||
300 | |||
301 | // "Location text" is actually the owner name, the original | ||
302 | // name that owner gave the parcel, and the location. | ||
303 | char buffer[256]; | ||
304 | LLString location_text; | ||
305 | |||
306 | msg->getString("Data", "User", 256, buffer); | ||
307 | location_text.assign(buffer); | ||
308 | location_text.append(", "); | ||
309 | |||
310 | msg->getString("Data", "OriginalName", 256, buffer); | ||
311 | if (buffer[0] != '\0') | ||
312 | { | ||
313 | location_text.append(buffer); | ||
314 | location_text.append(", "); | ||
315 | } | ||
316 | |||
317 | char sim_name[256]; | ||
318 | msg->getString("Data", "SimName", 256, sim_name); | ||
319 | |||
320 | LLVector3d pos_global; | ||
321 | msg->getVector3d("Data", "PosGlobal", pos_global); | ||
322 | |||
323 | S32 region_x = llround((F32)pos_global.mdV[VX]) % REGION_WIDTH_UNITS; | ||
324 | S32 region_y = llround((F32)pos_global.mdV[VY]) % REGION_WIDTH_UNITS; | ||
325 | S32 region_z = llround((F32)pos_global.mdV[VZ]); | ||
326 | |||
327 | sprintf(buffer, "%s (%d, %d, %d)", sim_name, region_x, region_y, region_z); | ||
328 | location_text.append(buffer); | ||
329 | |||
330 | S32 sort_order; | ||
331 | msg->getS32("Data", "SortOrder", sort_order); | ||
332 | |||
333 | BOOL enabled; | ||
334 | msg->getBOOL("Data", "Enabled", enabled); | ||
335 | |||
336 | // Look up the panel to fill in | ||
337 | LLPanelPick *self = NULL; | ||
338 | for (self = sAllPanels.getFirstData(); self; self = sAllPanels.getNextData()) | ||
339 | { | ||
340 | // For top picks, must match pick id | ||
341 | if (self->mPickID != pick_id) | ||
342 | { | ||
343 | continue; | ||
344 | } | ||
345 | |||
346 | self->mDataReceived = TRUE; | ||
347 | |||
348 | // Found the panel, now fill in the information | ||
349 | self->mPickID = pick_id; | ||
350 | self->mCreatorID = creator_id; | ||
351 | self->mParcelID = parcel_id; | ||
352 | self->mSimName.assign(sim_name); | ||
353 | self->mPosGlobal = pos_global; | ||
354 | |||
355 | // Update UI controls | ||
356 | self->mNameEditor->setText(name); | ||
357 | self->mDescEditor->setText(desc); | ||
358 | self->mSnapshotCtrl->setImageAssetID(snapshot_id); | ||
359 | self->mLocationEditor->setText(location_text); | ||
360 | self->mEnabledCheck->set(enabled); | ||
361 | |||
362 | sprintf(buffer, "%d", sort_order); | ||
363 | self->mSortOrderEditor->setText(buffer); | ||
364 | } | ||
365 | } | ||
366 | |||
367 | void LLPanelPick::draw() | ||
368 | { | ||
369 | if (getVisible()) | ||
370 | { | ||
371 | refresh(); | ||
372 | |||
373 | LLPanel::draw(); | ||
374 | } | ||
375 | } | ||
376 | |||
377 | |||
378 | void LLPanelPick::refresh() | ||
379 | { | ||
380 | if (!mDataRequested) | ||
381 | { | ||
382 | sendPickInfoRequest(); | ||
383 | } | ||
384 | |||
385 | // Check for god mode | ||
386 | BOOL godlike = gAgent.isGodlike(); | ||
387 | BOOL is_self = (gAgent.getID() == mCreatorID); | ||
388 | |||
389 | // Set button visibility/enablement appropriately | ||
390 | if (mTopPick) | ||
391 | { | ||
392 | mSnapshotCtrl->setEnabled(godlike); | ||
393 | mNameEditor->setEnabled(godlike); | ||
394 | mDescEditor->setEnabled(godlike); | ||
395 | |||
396 | mSortOrderText->setVisible(godlike); | ||
397 | |||
398 | mSortOrderEditor->setVisible(godlike); | ||
399 | mSortOrderEditor->setEnabled(godlike); | ||
400 | |||
401 | mEnabledCheck->setVisible(godlike); | ||
402 | mEnabledCheck->setEnabled(godlike); | ||
403 | |||
404 | mSetBtn->setVisible(godlike); | ||
405 | mSetBtn->setEnabled(godlike); | ||
406 | } | ||
407 | else | ||
408 | { | ||
409 | mSnapshotCtrl->setEnabled(is_self); | ||
410 | mNameEditor->setEnabled(is_self); | ||
411 | mDescEditor->setEnabled(is_self); | ||
412 | |||
413 | mSortOrderText->setVisible(FALSE); | ||
414 | |||
415 | mSortOrderEditor->setVisible(FALSE); | ||
416 | mSortOrderEditor->setEnabled(FALSE); | ||
417 | |||
418 | mEnabledCheck->setVisible(FALSE); | ||
419 | mEnabledCheck->setEnabled(FALSE); | ||
420 | |||
421 | mSetBtn->setVisible(is_self); | ||
422 | mSetBtn->setEnabled(is_self); | ||
423 | } | ||
424 | } | ||
425 | |||
426 | |||
427 | // static | ||
428 | void LLPanelPick::onClickTeleport(void* data) | ||
429 | { | ||
430 | LLPanelPick* self = (LLPanelPick*)data; | ||
431 | |||
432 | if (!self->mPosGlobal.isExactlyZero()) | ||
433 | { | ||
434 | gAgent.teleportViaLocation(self->mPosGlobal); | ||
435 | gFloaterWorldMap->trackLocation(self->mPosGlobal); | ||
436 | } | ||
437 | } | ||
438 | |||
439 | |||
440 | // static | ||
441 | void LLPanelPick::onClickMap(void* data) | ||
442 | { | ||
443 | LLPanelPick* self = (LLPanelPick*)data; | ||
444 | gFloaterWorldMap->trackLocation(self->mPosGlobal); | ||
445 | LLFloaterWorldMap::show(NULL, TRUE); | ||
446 | } | ||
447 | |||
448 | // static | ||
449 | /* | ||
450 | void LLPanelPick::onClickLandmark(void* data) | ||
451 | { | ||
452 | LLPanelPick* self = (LLPanelPick*)data; | ||
453 | create_landmark(self->mNameEditor->getText().c_str(), "", self->mPosGlobal); | ||
454 | } | ||
455 | */ | ||
456 | |||
457 | // static | ||
458 | void LLPanelPick::onClickSet(void* data) | ||
459 | { | ||
460 | LLPanelPick* self = (LLPanelPick*)data; | ||
461 | |||
462 | // Save location for later. | ||
463 | self->mPosGlobal = gAgent.getPositionGlobal(); | ||
464 | |||
465 | LLString location_text; | ||
466 | location_text.assign("(will update after save)"); | ||
467 | location_text.append(", "); | ||
468 | |||
469 | S32 region_x = llround((F32)self->mPosGlobal.mdV[VX]) % REGION_WIDTH_UNITS; | ||
470 | S32 region_y = llround((F32)self->mPosGlobal.mdV[VY]) % REGION_WIDTH_UNITS; | ||
471 | S32 region_z = llround((F32)self->mPosGlobal.mdV[VZ]); | ||
472 | |||
473 | location_text.append(self->mSimName); | ||
474 | location_text.append(llformat(" (%d, %d, %d)", region_x, region_y, region_z)); | ||
475 | |||
476 | // if sim name in pick is different from current sim name | ||
477 | // make sure it's clear that all that's being changed | ||
478 | // is the location and nothing else | ||
479 | if ( gAgent.getRegion ()->getName () != self->mSimName ) | ||
480 | { | ||
481 | gViewerWindow->alertXml("SetPickLocation"); | ||
482 | }; | ||
483 | |||
484 | self->mLocationEditor->setText(location_text); | ||
485 | |||
486 | onCommitAny(NULL, data); | ||
487 | } | ||
488 | |||
489 | |||
490 | // static | ||
491 | void LLPanelPick::onCommitAny(LLUICtrl* ctrl, void* data) | ||
492 | { | ||
493 | LLPanelPick* self = (LLPanelPick*)data; | ||
494 | |||
495 | // have we received up to date data for this pick? | ||
496 | if (self->mDataReceived) | ||
497 | { | ||
498 | self->sendPickInfoUpdate(); | ||
499 | |||
500 | // Big hack - assume that top picks are always in a browser, | ||
501 | // and non-top-picks are always in a tab container. | ||
502 | /*if (self->mTopPick) | ||
503 | { | ||
504 | LLPanelDirPicks* panel = (LLPanelDirPicks*)self->getParent(); | ||
505 | panel->renamePick(self->mPickID, self->mNameEditor->getText().c_str()); | ||
506 | } | ||
507 | else | ||
508 | {*/ | ||
509 | LLTabContainerVertical* tab = (LLTabContainerVertical*)self->getParent(); | ||
510 | tab->setCurrentTabName(self->mNameEditor->getText()); | ||
511 | //} | ||
512 | } | ||
513 | } | ||