llviewerparcelmgr.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "llviewerparcelmgr.h"
00035 
00036 // Library includes
00037 #include "audioengine.h"
00038 #include "indra_constants.h"
00039 #include "llcachename.h"
00040 #include "llgl.h"
00041 #include "llmediaengine.h"
00042 #include "llparcel.h"
00043 #include "llsecondlifeurls.h"
00044 #include "message.h"
00045 
00046 // Viewer includes
00047 #include "llagent.h"
00048 #include "llfloatergroupinfo.h"
00049 #include "llviewerwindow.h"
00050 #include "llviewercontrol.h"
00051 #include "llfirstuse.h"
00052 #include "llfloaterbuyland.h"
00053 #include "llfloatergroups.h"
00054 //#include "llfloaterhtml.h"
00055 #include "llfloatersellland.h"
00056 #include "llfloatertools.h"
00057 #include "llnotify.h"
00058 #include "llresmgr.h"
00059 #include "llstatusbar.h"
00060 #include "llui.h"
00061 #include "llviewerimagelist.h"
00062 #include "llviewermenu.h"
00063 #include "llviewerparceloverlay.h"
00064 #include "llviewerregion.h"
00065 //#include "llwebbrowserctrl.h"
00066 #include "llworld.h"
00067 #include "lloverlaybar.h"
00068 #include "roles_constants.h"
00069 
00070 const F32 PARCEL_COLLISION_DRAW_SECS = 1.f;
00071 
00072 
00073 // Globals
00074 LLViewerParcelMgr *gParcelMgr = NULL;
00075 
00076 U8* LLViewerParcelMgr::sPackedOverlay = NULL;
00077 
00078 LLUUID gCurrentMovieID = LLUUID::null;
00079 
00080 static LLParcelSelection* get_null_parcel_selection();
00081 template<> 
00082         const LLHandle<LLParcelSelection>::NullFunc 
00083                 LLHandle<LLParcelSelection>::sNullFunc = get_null_parcel_selection;
00084 
00085 
00086 // Local functions
00087 void optionally_start_music(const LLString& music_url);
00088 void callback_start_music(S32 option, void* data);
00089 void optionally_prepare_video(const LLParcel *parcelp);
00090 void callback_prepare_video(S32 option, void* data);
00091 void prepare_video(const LLParcel *parcelp);
00092 void start_video(const LLParcel *parcelp);
00093 void stop_video();
00094 void callback_god_force_owner(S32 option, void* user_data);
00095 
00096 struct LLGodForceOwnerData
00097 {
00098         LLUUID mOwnerID;
00099         S32 mLocalID;
00100         LLHost mHost;
00101 
00102         LLGodForceOwnerData(
00103                 const LLUUID& owner_id,
00104                 S32 local_parcel_id,
00105                 const LLHost& host) :
00106                 mOwnerID(owner_id),
00107                 mLocalID(local_parcel_id),
00108                 mHost(host) {}
00109 };
00110 
00111 //
00112 // Methods
00113 //
00114 LLViewerParcelMgr::LLViewerParcelMgr()
00115 :       mSelected(FALSE),
00116         mWestSouth(),
00117         mEastNorth(),
00118         mSelectedDwell(0.f),
00119         mAgentParcelSequenceID(-1),
00120         mHoverWestSouth(),
00121         mHoverEastNorth(),
00122         mRenderCollision(FALSE),
00123         mRenderSelection(TRUE),
00124         mCollisionBanned(0),
00125         mCollisionTimer()
00126 {
00127         mCurrentParcel = new LLParcel();
00128         mCurrentParcelSelection = new LLParcelSelection(mCurrentParcel);
00129         mFloatingParcelSelection = new LLParcelSelection(mCurrentParcel);
00130 
00131         mAgentParcel = new LLParcel();
00132         mHoverParcel = new LLParcel();
00133         mCollisionParcel = new LLParcel();
00134 
00135         mParcelsPerEdge = S32(  REGION_WIDTH_METERS / PARCEL_GRID_STEP_METERS );
00136         mHighlightSegments = new U8[(mParcelsPerEdge+1)*(mParcelsPerEdge+1)];
00137         resetSegments(mHighlightSegments);
00138 
00139         mCollisionSegments = new U8[(mParcelsPerEdge+1)*(mParcelsPerEdge+1)];
00140         resetSegments(mCollisionSegments);
00141 
00142         mBlockedImageID.set(gViewerArt.getString("noentrylines.tga"));
00143         mBlockedImage = gImageList.getImage(mBlockedImageID, TRUE, TRUE);
00144 
00145         mPassImageID.set(gViewerArt.getString("noentrypasslines.tga"));
00146         mPassImage = gImageList.getImage(mPassImageID, TRUE, TRUE);
00147 
00148         S32 overlay_size = mParcelsPerEdge * mParcelsPerEdge / PARCEL_OVERLAY_CHUNKS;
00149         sPackedOverlay = new U8[overlay_size];
00150 
00151         mAgentParcelOverlay = new U8[mParcelsPerEdge * mParcelsPerEdge];
00152         S32 i;
00153         for (i = 0; i < mParcelsPerEdge * mParcelsPerEdge; i++)
00154         {
00155                 mAgentParcelOverlay[i] = 0;
00156         }
00157 }
00158 
00159 
00160 LLViewerParcelMgr::~LLViewerParcelMgr()
00161 {
00162         mCurrentParcelSelection->setParcel(NULL);
00163         mCurrentParcelSelection = NULL;
00164 
00165         mFloatingParcelSelection->setParcel(NULL);
00166         mFloatingParcelSelection = NULL;
00167 
00168         delete mCurrentParcel;
00169         mCurrentParcel = NULL;
00170 
00171         delete mAgentParcel;
00172         mAgentParcel = NULL;
00173 
00174         delete mCollisionParcel;
00175         mCollisionParcel = NULL;
00176 
00177         delete mHoverParcel;
00178         mHoverParcel = NULL;
00179 
00180         delete[] mHighlightSegments;
00181         mHighlightSegments = NULL;
00182 
00183         delete[] mCollisionSegments;
00184         mCollisionSegments = NULL;
00185 
00186         delete[] sPackedOverlay;
00187         sPackedOverlay = NULL;
00188 
00189         delete[] mAgentParcelOverlay;
00190         mAgentParcelOverlay = NULL;
00191 }
00192 
00193 void LLViewerParcelMgr::dump()
00194 {
00195         llinfos << "Parcel Manager Dump" << llendl;
00196         llinfos << "mSelected " << S32(mSelected) << llendl;
00197         llinfos << "Selected parcel: " << llendl;
00198         llinfos << mWestSouth << " to " << mEastNorth << llendl;
00199         mCurrentParcel->dump();
00200         llinfos << "banning " << mCurrentParcel->mBanList.size() << llendl;
00201         
00202         access_map_const_iterator cit = mCurrentParcel->mBanList.begin();
00203         access_map_const_iterator end = mCurrentParcel->mBanList.end();
00204         for ( ; cit != end; ++cit)
00205         {
00206                 llinfos << "ban id " << (*cit).first << llendl;
00207         }
00208         llinfos << "Hover parcel:" << llendl;
00209         mHoverParcel->dump();
00210         llinfos << "Agent parcel:" << llendl;
00211         mAgentParcel->dump();
00212 }
00213 
00214 
00215 LLViewerRegion* LLViewerParcelMgr::getSelectionRegion()
00216 {
00217         if (!gWorldp) return NULL;
00218 
00219         return gWorldp->getRegionFromPosGlobal( mWestSouth );
00220 }
00221 
00222 
00223 void LLViewerParcelMgr::getDisplayInfo(S32* area_out, S32* claim_out,
00224                                                                            S32* rent_out,
00225                                                                            BOOL* for_sale_out,
00226                                                                            F32* dwell_out)
00227 {
00228         S32 area = 0;
00229         S32 price = 0;
00230         S32 rent = 0;
00231         BOOL for_sale = FALSE;
00232         F32 dwell = 0.f;
00233 
00234         if (mSelected)
00235         {
00236                 if (mCurrentParcelSelection->mSelectedMultipleOwners)
00237                 {
00238                         area = mCurrentParcelSelection->getClaimableArea();
00239                 }
00240                 else
00241                 {
00242                         area = getSelectedArea();
00243                 }
00244 
00245                 if (mCurrentParcel->getForSale())
00246                 {
00247                         price = mCurrentParcel->getSalePrice();
00248                         for_sale = TRUE;
00249                 }
00250                 else
00251                 {
00252                         price = area * mCurrentParcel->getClaimPricePerMeter();
00253                         for_sale = FALSE;
00254                 }
00255 
00256                 rent = mCurrentParcel->getTotalRent();
00257 
00258                 dwell = mSelectedDwell;
00259         }
00260 
00261         *area_out = area;
00262         *claim_out = price;
00263         *rent_out = rent;
00264         *for_sale_out = for_sale;
00265         *dwell_out = dwell;
00266 }
00267 
00268 void LLViewerParcelMgr::getPrimInfo(S32 &sw_max, S32 &sw_total, S32 &max, S32 &total, S32 &owner, S32 &group, S32 &other, S32& selected, F32 &parcel_object_bonus, S32 &other_clean)
00269 {
00270         if (mSelected && mCurrentParcel)
00271         {
00272                 sw_max = mCurrentParcel->getSimWideMaxPrimCapacity();
00273                 sw_total = mCurrentParcel->getSimWidePrimCount();
00274                 max = llround(mCurrentParcel->getMaxPrimCapacity()*mCurrentParcel->getParcelPrimBonus());
00275                 total = mCurrentParcel->getPrimCount();
00276                 owner = mCurrentParcel->getOwnerPrimCount();
00277                 group = mCurrentParcel->getGroupPrimCount();
00278                 other = mCurrentParcel->getOtherPrimCount();
00279                 selected = mCurrentParcel->getSelectedPrimCount();
00280                 parcel_object_bonus = mCurrentParcel->getParcelPrimBonus();
00281                 other_clean = mCurrentParcel->getCleanOtherTime();
00282         }
00283 }
00284 
00285 S32 LLViewerParcelMgr::getSelectedArea() const
00286 {
00287         S32 rv = 0;
00288         if(mSelected && mCurrentParcel && mCurrentParcelSelection->mWholeParcelSelected)
00289         {
00290                 rv = mCurrentParcel->getArea();
00291         }
00292         else if(mSelected)
00293         {
00294                 F64 width = mEastNorth.mdV[VX] - mWestSouth.mdV[VX];
00295                 F64 height = mEastNorth.mdV[VY] - mWestSouth.mdV[VY];
00296                 F32 area = (F32)(width * height);
00297                 rv = llround(area);
00298         }
00299         return rv;
00300 }
00301 
00302 void LLViewerParcelMgr::resetSegments(U8* segments)
00303 {
00304         S32 i;
00305         S32 count = (mParcelsPerEdge+1)*(mParcelsPerEdge+1);
00306         for (i = 0; i < count; i++)
00307         {
00308                 segments[i] = 0x0;
00309         }
00310 }
00311 
00312 
00313 void LLViewerParcelMgr::writeHighlightSegments(F32 west, F32 south, F32 east,
00314                                                                                            F32 north)
00315 {
00316         S32 x, y;
00317         S32 min_x = llround( west / PARCEL_GRID_STEP_METERS );
00318         S32 max_x = llround( east / PARCEL_GRID_STEP_METERS );
00319         S32 min_y = llround( south / PARCEL_GRID_STEP_METERS );
00320         S32 max_y = llround( north / PARCEL_GRID_STEP_METERS );
00321 
00322         const S32 STRIDE = mParcelsPerEdge+1;
00323 
00324         // south edge
00325         y = min_y;
00326         for (x = min_x; x < max_x; x++)
00327         {
00328                 // exclusive OR means that writing to this segment twice
00329                 // will turn it off
00330                 mHighlightSegments[x + y*STRIDE] ^= SOUTH_MASK;
00331         }
00332 
00333         // west edge
00334         x = min_x;
00335         for (y = min_y; y < max_y; y++)
00336         {
00337                 mHighlightSegments[x + y*STRIDE] ^= WEST_MASK;
00338         }
00339 
00340         // north edge - draw the south border on the y+1'th cell,
00341         // which given C-style arrays, is item foo[max_y]
00342         y = max_y;
00343         for (x = min_x; x < max_x; x++)
00344         {
00345                 mHighlightSegments[x + y*STRIDE] ^= SOUTH_MASK;
00346         }
00347 
00348         // east edge - draw west border on x+1'th cell
00349         x = max_x;
00350         for (y = min_y; y < max_y; y++)
00351         {
00352                 mHighlightSegments[x + y*STRIDE] ^= WEST_MASK;
00353         }
00354 }
00355 
00356 
00357 void LLViewerParcelMgr::writeSegmentsFromBitmap(U8* bitmap, U8* segments)
00358 {
00359         S32 x;
00360         S32 y;
00361         const S32 IN_STRIDE = mParcelsPerEdge;
00362         const S32 OUT_STRIDE = mParcelsPerEdge+1;
00363 
00364         for (y = 0; y < IN_STRIDE; y++)
00365         {
00366                 x = 0;
00367                 while( x < IN_STRIDE )
00368                 {
00369                         U8 byte = bitmap[ (x + y*IN_STRIDE) / 8 ];
00370 
00371                         S32 bit;
00372                         for (bit = 0; bit < 8; bit++)
00373                         {
00374                                 if (byte & (1 << bit) )
00375                                 {
00376                                         S32 out = x+y*OUT_STRIDE;
00377 
00378                                         // This and one above it
00379                                         segments[out]            ^= SOUTH_MASK;
00380                                         segments[out+OUT_STRIDE] ^= SOUTH_MASK;
00381 
00382                                         // This and one to the right
00383                                         segments[out]   ^= WEST_MASK;
00384                                         segments[out+1] ^= WEST_MASK;
00385                                 }
00386                                 x++;
00387                         }
00388                 }
00389         }
00390 }
00391 
00392 
00393 void LLViewerParcelMgr::writeAgentParcelFromBitmap(U8* bitmap)
00394 {
00395         S32 x;
00396         S32 y;
00397         const S32 IN_STRIDE = mParcelsPerEdge;
00398 
00399         for (y = 0; y < IN_STRIDE; y++)
00400         {
00401                 x = 0;
00402                 while( x < IN_STRIDE )
00403                 {
00404                         U8 byte = bitmap[ (x + y*IN_STRIDE) / 8 ];
00405 
00406                         S32 bit;
00407                         for (bit = 0; bit < 8; bit++)
00408                         {
00409                                 if (byte & (1 << bit) )
00410                                 {
00411                                         mAgentParcelOverlay[x+y*IN_STRIDE] = 1;
00412                                 }
00413                                 else
00414                                 {
00415                                         mAgentParcelOverlay[x+y*IN_STRIDE] = 0;
00416                                 }
00417                                 x++;
00418                         }
00419                 }
00420         }
00421 }
00422 
00423 
00424 // Given a point, find the PARCEL_GRID_STEP x PARCEL_GRID_STEP block
00425 // containing it and select that.
00426 LLParcelSelectionHandle LLViewerParcelMgr::selectParcelAt(const LLVector3d& pos_global)
00427 {
00428         LLVector3d southwest = pos_global;
00429         LLVector3d northeast = pos_global;
00430 
00431         southwest -= LLVector3d( PARCEL_GRID_STEP_METERS/2, PARCEL_GRID_STEP_METERS/2, 0 );
00432         southwest.mdV[VX] = llround( southwest.mdV[VX], (F64)PARCEL_GRID_STEP_METERS );
00433         southwest.mdV[VY] = llround( southwest.mdV[VY], (F64)PARCEL_GRID_STEP_METERS );
00434 
00435         northeast += LLVector3d( PARCEL_GRID_STEP_METERS/2, PARCEL_GRID_STEP_METERS/2, 0 );
00436         northeast.mdV[VX] = llround( northeast.mdV[VX], (F64)PARCEL_GRID_STEP_METERS );
00437         northeast.mdV[VY] = llround( northeast.mdV[VY], (F64)PARCEL_GRID_STEP_METERS );
00438 
00439         // Snap to parcel
00440         return selectLand( southwest, northeast, TRUE );
00441 }
00442 
00443 
00444 // Tries to select the parcel inside the rectangle
00445 LLParcelSelectionHandle LLViewerParcelMgr::selectParcelInRectangle()
00446 {
00447         return selectLand(mWestSouth, mEastNorth, TRUE);
00448 }
00449 
00450 
00451 void LLViewerParcelMgr::selectCollisionParcel()
00452 {
00453         if (!gWorldp)
00454         {
00455                 return;
00456         }
00457 
00458         // BUG: Claim to be in the agent's region
00459         mWestSouth = gAgent.getRegion()->getOriginGlobal();
00460         mEastNorth = mWestSouth;
00461         mEastNorth += LLVector3d(PARCEL_GRID_STEP_METERS, PARCEL_GRID_STEP_METERS, 0.0);
00462 
00463         // BUG: must be in the sim you are in
00464         LLMessageSystem *msg = gMessageSystem;
00465         msg->newMessageFast(_PREHASH_ParcelPropertiesRequestByID);
00466         msg->nextBlockFast(_PREHASH_AgentID);
00467         msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
00468         msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
00469         msg->nextBlockFast(_PREHASH_ParcelData);
00470         msg->addS32Fast(_PREHASH_SequenceID, SELECTED_PARCEL_SEQ_ID );
00471         msg->addS32Fast(_PREHASH_LocalID, mCollisionParcel->getLocalID() );
00472         gAgent.sendReliableMessage();
00473 
00474         mRequestResult = PARCEL_RESULT_NO_DATA;
00475 
00476         // Hack: Copy some data over temporarily
00477         mCurrentParcel->setName( mCollisionParcel->getName() );
00478         mCurrentParcel->setDesc( mCollisionParcel->getDesc() );
00479         mCurrentParcel->setPassPrice(mCollisionParcel->getPassPrice());
00480         mCurrentParcel->setPassHours(mCollisionParcel->getPassHours());
00481 
00482         // clear the list of segments to prevent flashing
00483         resetSegments(mHighlightSegments);
00484 
00485         mFloatingParcelSelection->setParcel(mCurrentParcel);
00486         mCurrentParcelSelection->setParcel(NULL);
00487         mCurrentParcelSelection = new LLParcelSelection(mCurrentParcel);
00488 
00489         mSelected = TRUE;
00490         mCurrentParcelSelection->mWholeParcelSelected = TRUE;
00491         notifyObservers();
00492         return;
00493 }
00494 
00495 
00496 // snap_selection = auto-select the hit parcel, if there is exactly one
00497 LLParcelSelectionHandle LLViewerParcelMgr::selectLand(const LLVector3d &corner1, const LLVector3d &corner2,
00498                                                                    BOOL snap_selection)
00499 {
00500         if (!gWorldp)
00501         {
00502                 return NULL;
00503         }
00504 
00505         sanitize_corners( corner1, corner2, mWestSouth, mEastNorth );
00506 
00507         // ...x isn't more than one meter away
00508         F32 delta_x = getSelectionWidth();
00509         if (delta_x * delta_x <= 1.f * 1.f)
00510         {
00511                 mSelected = FALSE;
00512                 notifyObservers();
00513                 return NULL;
00514         }
00515 
00516         // ...y isn't more than one meter away
00517         F32 delta_y = getSelectionHeight();
00518         if (delta_y * delta_y <= 1.f * 1.f)
00519         {
00520                 mSelected = FALSE;
00521                 notifyObservers();
00522                 return NULL;
00523         }
00524 
00525         // Can't select across region boundary
00526         // We need to pull in the upper right corner by a little bit to allow
00527         // selection up to the x = 256 or y = 256 edge.
00528         LLVector3d east_north_region_check( mEastNorth );
00529         east_north_region_check.mdV[VX] -= 0.5;
00530         east_north_region_check.mdV[VY] -= 0.5;
00531 
00532         LLViewerRegion *region = gWorldp->getRegionFromPosGlobal(mWestSouth);
00533         LLViewerRegion *region_other = gWorldp->getRegionFromPosGlobal( east_north_region_check );
00534 
00535         if(!region)
00536         {
00537                 // just in case they somehow selected no land.
00538                 mSelected = FALSE;
00539                 return NULL;
00540         }
00541 
00542         if (region != region_other)
00543         {
00544                 LLNotifyBox::showXml("CantSelectLandFromMultipleRegions");
00545                 mSelected = FALSE;
00546                 notifyObservers();
00547                 return NULL;
00548         }
00549 
00550         // Build region global copies of corners
00551         LLVector3 wsb_region = region->getPosRegionFromGlobal( mWestSouth );
00552         LLVector3 ent_region = region->getPosRegionFromGlobal( mEastNorth );
00553 
00554         // Send request message
00555         LLMessageSystem *msg = gMessageSystem;
00556         msg->newMessageFast(_PREHASH_ParcelPropertiesRequest);
00557         msg->nextBlockFast(_PREHASH_AgentData);
00558         msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
00559         msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
00560         msg->nextBlockFast(_PREHASH_ParcelData);
00561         msg->addS32Fast(_PREHASH_SequenceID, SELECTED_PARCEL_SEQ_ID );
00562         msg->addF32Fast(_PREHASH_West,  wsb_region.mV[VX] );
00563         msg->addF32Fast(_PREHASH_South, wsb_region.mV[VY] );
00564         msg->addF32Fast(_PREHASH_East,  ent_region.mV[VX] );
00565         msg->addF32Fast(_PREHASH_North, ent_region.mV[VY] );
00566         msg->addBOOL("SnapSelection", snap_selection);
00567         msg->sendReliable( region->getHost() );
00568 
00569         mRequestResult = PARCEL_RESULT_NO_DATA;
00570 
00571         // clear the list of segments to prevent flashing
00572         resetSegments(mHighlightSegments);
00573 
00574         mFloatingParcelSelection->setParcel(mCurrentParcel);
00575         mCurrentParcelSelection->setParcel(NULL);
00576         mCurrentParcelSelection = new LLParcelSelection(mCurrentParcel);
00577 
00578         mSelected = TRUE;
00579         mCurrentParcelSelection->mWholeParcelSelected = snap_selection;
00580         notifyObservers();
00581         return mCurrentParcelSelection;
00582 }
00583 
00584 void LLViewerParcelMgr::deselectUnused()
00585 {
00586         // no more outstanding references to this selection, other than our own
00587         if (mCurrentParcelSelection->getNumRefs() == 1 && mFloatingParcelSelection->getNumRefs() == 1)
00588         {
00589                 deselectLand();
00590         }
00591 }
00592 
00593 void LLViewerParcelMgr::deselectLand()
00594 {
00595         if (mSelected)
00596         {
00597                 mSelected = FALSE;
00598 
00599                 // Invalidate the selected parcel
00600                 mCurrentParcel->setLocalID(-1);
00601                 mCurrentParcel->mAccessList.clear();
00602                 mCurrentParcel->mBanList.clear();
00603                 //mCurrentParcel->mRenterList.reset();
00604 
00605                 mSelectedDwell = 0.f;
00606 
00607                 notifyObservers();
00608 
00609                 // invalidate parcel selection so that existing users of this selection can clean up
00610                 mCurrentParcelSelection->setParcel(NULL);
00611                 mFloatingParcelSelection->setParcel(NULL);
00612                 // create new parcel selection
00613                 mCurrentParcelSelection = new LLParcelSelection(mCurrentParcel);
00614         }
00615 }
00616 
00617 
00618 void LLViewerParcelMgr::addObserver(LLParcelObserver* observer)
00619 {
00620         mObservers.put(observer);
00621 }
00622 
00623 
00624 void LLViewerParcelMgr::removeObserver(LLParcelObserver* observer)
00625 {
00626         mObservers.removeObj(observer);
00627 }
00628 
00629 
00630 // Call this method when it's time to update everyone on a new state.
00631 // Copy the list because an observer could respond by removing itself
00632 // from the list.
00633 void LLViewerParcelMgr::notifyObservers()
00634 {
00635         LLDynamicArray<LLParcelObserver*> observers;
00636         S32 count = mObservers.count();
00637         S32 i;
00638         for(i = 0; i < count; ++i)
00639         {
00640                 observers.put(mObservers.get(i));
00641         }
00642         for(i = 0; i < count; ++i)
00643         {
00644                 observers.get(i)->changed();
00645         }
00646 }
00647 
00648 
00649 //
00650 // ACCESSORS
00651 //
00652 BOOL LLViewerParcelMgr::selectionEmpty() const
00653 {
00654         return !mSelected;
00655 }
00656 
00657 
00658 LLParcelSelectionHandle LLViewerParcelMgr::getParcelSelection() const
00659 {
00660         return mCurrentParcelSelection;
00661 }
00662 
00663 LLParcelSelectionHandle LLViewerParcelMgr::getFloatingParcelSelection() const
00664 {
00665         return mFloatingParcelSelection;
00666 }
00667 
00668 LLParcel *LLViewerParcelMgr::getAgentParcel() const
00669 {
00670         return mAgentParcel;
00671 }
00672 
00673 // Return whether the agent can build on the land they are on
00674 BOOL LLViewerParcelMgr::agentCanBuild() const
00675 {
00676         if (mAgentParcel)
00677         {
00678                 return (gAgent.isGodlike()
00679                                 || (mAgentParcel->allowModifyBy(
00680                                                 gAgent.getID(),
00681                                                 gAgent.getGroupID())));
00682         }
00683         else
00684         {
00685                 return gAgent.isGodlike();
00686         }
00687 }
00688 
00689 BOOL LLViewerParcelMgr::agentCanTakeDamage() const
00690 {
00691         return mAgentParcel->getAllowDamage();
00692 }
00693 
00694 BOOL LLViewerParcelMgr::agentCanFly() const
00695 {
00696         return TRUE;
00697 }
00698 
00699 F32 LLViewerParcelMgr::agentDrawDistance() const
00700 {
00701         return 512.f;
00702 }
00703 
00704 BOOL LLViewerParcelMgr::isOwnedAt(const LLVector3d& pos_global) const
00705 {
00706         LLViewerRegion* region = gWorldp->getRegionFromPosGlobal( pos_global );
00707         if (!region) return FALSE;
00708 
00709         LLViewerParcelOverlay* overlay = region->getParcelOverlay();
00710         if (!overlay) return FALSE;
00711 
00712         LLVector3 pos_region = region->getPosRegionFromGlobal( pos_global );
00713 
00714         return overlay->isOwned( pos_region );
00715 }
00716 
00717 BOOL LLViewerParcelMgr::isOwnedSelfAt(const LLVector3d& pos_global) const
00718 {
00719         LLViewerRegion* region = gWorldp->getRegionFromPosGlobal( pos_global );
00720         if (!region) return FALSE;
00721 
00722         LLViewerParcelOverlay* overlay = region->getParcelOverlay();
00723         if (!overlay) return FALSE;
00724 
00725         LLVector3 pos_region = region->getPosRegionFromGlobal( pos_global );
00726 
00727         return overlay->isOwnedSelf( pos_region );
00728 }
00729 
00730 BOOL LLViewerParcelMgr::isOwnedOtherAt(const LLVector3d& pos_global) const
00731 {
00732         LLViewerRegion* region = gWorldp->getRegionFromPosGlobal( pos_global );
00733         if (!region) return FALSE;
00734 
00735         LLViewerParcelOverlay* overlay = region->getParcelOverlay();
00736         if (!overlay) return FALSE;
00737 
00738         LLVector3 pos_region = region->getPosRegionFromGlobal( pos_global );
00739 
00740         return overlay->isOwnedOther( pos_region );
00741 }
00742 
00743 BOOL LLViewerParcelMgr::isSoundLocal(const LLVector3d& pos_global) const
00744 {
00745         LLViewerRegion* region = gWorldp->getRegionFromPosGlobal( pos_global );
00746         if (!region) return FALSE;
00747 
00748         LLViewerParcelOverlay* overlay = region->getParcelOverlay();
00749         if (!overlay) return FALSE;
00750 
00751         LLVector3 pos_region = region->getPosRegionFromGlobal( pos_global );
00752 
00753         return overlay->isSoundLocal( pos_region );
00754 }
00755 
00756 BOOL LLViewerParcelMgr::canHearSound(const LLVector3d &pos_global) const
00757 {
00758         BOOL in_agent_parcel = inAgentParcel(pos_global);
00759 
00760         if (in_agent_parcel)
00761         {
00762                 // In same parcel as the agent
00763                 return TRUE;
00764         }
00765         else
00766         {
00767                 if (gParcelMgr->getAgentParcel()->getSoundLocal())
00768                 {
00769                         // Not in same parcel, and agent parcel only has local sound
00770                         return FALSE;
00771                 }
00772                 else if (gParcelMgr->isSoundLocal(pos_global))
00773                 {
00774                         // Not in same parcel, and target parcel only has local sound
00775                         return FALSE;
00776                 }
00777                 else
00778                 {
00779                         // Not in same parcel, but neither are local sound
00780                         return TRUE;
00781                 }
00782         }
00783 }
00784 
00785 
00786 BOOL LLViewerParcelMgr::inAgentParcel(const LLVector3d &pos_global) const
00787 {
00788         LLViewerRegion* region = gWorldp->getRegionFromPosGlobal(pos_global);
00789         if (region != gAgent.getRegion())
00790         {
00791                 // Can't be in the agent parcel if you're not in the same region.
00792                 return FALSE;
00793         }
00794 
00795         LLVector3 pos_region = gAgent.getRegion()->getPosRegionFromGlobal(pos_global);
00796         S32 row =    S32(pos_region.mV[VY] / PARCEL_GRID_STEP_METERS);
00797         S32 column = S32(pos_region.mV[VX] / PARCEL_GRID_STEP_METERS);
00798 
00799         if (mAgentParcelOverlay[row*mParcelsPerEdge + column])
00800         {
00801                 return TRUE;
00802         }
00803         else
00804         {
00805                 return FALSE;
00806         }
00807 }
00808 
00809 // Returns NULL when there is no valid data.
00810 LLParcel* LLViewerParcelMgr::getHoverParcel() const
00811 {
00812         if (mHoverRequestResult == PARCEL_RESULT_SUCCESS)
00813         {
00814                 return mHoverParcel;
00815         }
00816         else
00817         {
00818                 return NULL;
00819         }
00820 }
00821 
00822 // Returns NULL when there is no valid data.
00823 LLParcel* LLViewerParcelMgr::getCollisionParcel() const
00824 {
00825         if (mRenderCollision)
00826         {
00827                 return mCollisionParcel;
00828         }
00829         else
00830         {
00831                 return NULL;
00832         }
00833 }
00834 
00835 //
00836 // UTILITIES
00837 //
00838 
00839 void LLViewerParcelMgr::render()
00840 {
00841         if (mSelected && mRenderSelection)
00842         {
00843                 // Rendering is done in agent-coordinates, so need to supply
00844                 // an appropriate offset to the render code.
00845                 LLViewerRegion *regionp = gWorldp->getRegionFromPosGlobal( mWestSouth );
00846                 if (!regionp) return;
00847 
00848                 renderHighlightSegments(mHighlightSegments, regionp);
00849         }
00850 }
00851 
00852 
00853 void LLViewerParcelMgr::renderParcelCollision()
00854 {
00855         // check for expiration
00856         if (mCollisionTimer.getElapsedTimeF32() > PARCEL_COLLISION_DRAW_SECS)
00857         {
00858                 mRenderCollision = FALSE;
00859         }
00860 
00861         if (mRenderCollision)
00862         {
00863                 LLViewerRegion* regionp = gAgent.getRegion();
00864                 BOOL use_pass = mCollisionParcel->getParcelFlag(PF_USE_PASS_LIST);
00865                 renderCollisionSegments(mCollisionSegments, use_pass, regionp);
00866         }
00867 }
00868 
00869 
00870 void LLViewerParcelMgr::sendParcelAccessListRequest(U32 flags)
00871 {
00872         if (!mSelected)
00873         {
00874                 return;
00875         }
00876 
00877         LLViewerRegion *region = gWorldp->getRegionFromPosGlobal( mWestSouth );
00878         if (!region) return;
00879 
00880         LLMessageSystem *msg = gMessageSystem;
00881         
00882 
00883         if (flags & AL_BAN) 
00884         {
00885                 mCurrentParcel->mBanList.clear();
00886         }
00887         if (flags & AL_ACCESS) 
00888         {
00889                 mCurrentParcel->mAccessList.clear();
00890         }               
00891 
00892         // Only the headers differ
00893         msg->newMessageFast(_PREHASH_ParcelAccessListRequest);
00894         msg->nextBlockFast(_PREHASH_AgentData);
00895         msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
00896         msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00897         msg->nextBlockFast(_PREHASH_Data);
00898         msg->addS32Fast(_PREHASH_SequenceID, 0);
00899         msg->addU32Fast(_PREHASH_Flags, flags);
00900         msg->addS32("LocalID", mCurrentParcel->getLocalID() );
00901         msg->sendReliable( region->getHost() );
00902 }
00903 
00904 
00905 void LLViewerParcelMgr::sendParcelDwellRequest()
00906 {
00907         if (!mSelected)
00908         {
00909                 return;
00910         }
00911 
00912         LLViewerRegion *region = gWorldp->getRegionFromPosGlobal( mWestSouth );
00913         if (!region) return;
00914 
00915         LLMessageSystem *msg = gMessageSystem;
00916 
00917         // Only the headers differ
00918         msg->newMessage("ParcelDwellRequest");
00919         msg->nextBlock("AgentData");
00920         msg->addUUID("AgentID", gAgent.getID() );
00921         msg->addUUID("SessionID", gAgent.getSessionID());
00922         msg->nextBlock("Data");
00923         msg->addS32("LocalID", mCurrentParcel->getLocalID());
00924         msg->addUUID("ParcelID", LLUUID::null); // filled in on simulator
00925         msg->sendReliable( region->getHost() );
00926 }
00927 
00928 
00929 void LLViewerParcelMgr::sendParcelGodForceOwner(const LLUUID& owner_id)
00930 {
00931         if (!mSelected)
00932         {
00933                 gViewerWindow->alertXml("CannotSetLandOwnerNothingSelected");
00934                 return;
00935         }
00936 
00937         llinfos << "Claiming " << mWestSouth << " to " << mEastNorth << llendl;
00938 
00939         // BUG: Only works for the region containing mWestSouthBottom
00940         LLVector3d east_north_region_check( mEastNorth );
00941         east_north_region_check.mdV[VX] -= 0.5;
00942         east_north_region_check.mdV[VY] -= 0.5;
00943 
00944         LLViewerRegion *region = gWorldp->getRegionFromPosGlobal( mWestSouth );
00945         if (!region)
00946         {
00947                 // TODO: Add a force owner version of this alert.
00948                 gViewerWindow->alertXml("CannotContentifyNoRegion");
00949                 return;
00950         }
00951 
00952         // BUG: Make work for cross-region selections
00953         LLViewerRegion *region2 = gWorldp->getRegionFromPosGlobal( east_north_region_check );
00954         if (region != region2)
00955         {
00956                 gViewerWindow->alertXml("CannotSetLandOwnerMultipleRegions");
00957                 return;
00958         }
00959 
00960         llinfos << "Region " << region->getOriginGlobal() << llendl;
00961 
00962         LLGodForceOwnerData* data = new LLGodForceOwnerData(owner_id, mCurrentParcel->getLocalID(), region->getHost());
00963         if(mCurrentParcel->getAuctionID())
00964         {
00965                 gViewerWindow->alertXml("ForceOwnerAuctionWarning",
00966                         callback_god_force_owner,
00967                         (void*)data);
00968         }
00969         else
00970         {
00971                 callback_god_force_owner(0, (void*)data);
00972         }
00973 }
00974 
00975 void callback_god_force_owner(S32 option, void* user_data)
00976 {
00977         LLGodForceOwnerData* data = (LLGodForceOwnerData*)user_data;
00978         if(data && (0 == option))
00979         {
00980                 LLMessageSystem* msg = gMessageSystem;
00981                 msg->newMessage("ParcelGodForceOwner");
00982                 msg->nextBlock("AgentData");
00983                 msg->addUUID("AgentID", gAgent.getID());
00984                 msg->addUUID("SessionID", gAgent.getSessionID());
00985                 msg->nextBlock("Data");
00986                 msg->addUUID("OwnerID", data->mOwnerID);
00987                 msg->addS32( "LocalID", data->mLocalID);
00988                 msg->sendReliable(data->mHost);
00989         }
00990         delete data;
00991 }
00992 
00993 void LLViewerParcelMgr::sendParcelGodForceToContent()
00994 {
00995         if (!mSelected)
00996         {
00997                 gViewerWindow->alertXml("CannotContentifyNothingSelected");
00998                 return;
00999         }
01000         LLViewerRegion *region = gWorldp->getRegionFromPosGlobal( mWestSouth );
01001         if (!region)
01002         {
01003                 gViewerWindow->alertXml("CannotContentifyNoRegion");
01004                 return;
01005         }
01006 
01007         LLMessageSystem* msg = gMessageSystem;
01008         msg->newMessage("ParcelGodMarkAsContent");
01009         msg->nextBlock("AgentData");
01010         msg->addUUID("AgentID", gAgent.getID());
01011         msg->addUUID("SessionID", gAgent.getSessionID());
01012         msg->nextBlock("ParcelData");
01013         msg->addS32("LocalID", mCurrentParcel->getLocalID());
01014         msg->sendReliable(region->getHost());
01015 }
01016 
01017 void LLViewerParcelMgr::sendParcelRelease()
01018 {
01019         if (!mSelected)
01020         {
01021         gViewerWindow->alertXml("CannotReleaseLandNothingSelected");
01022                 return;
01023         }
01024 
01025         LLViewerRegion *region = gWorldp->getRegionFromPosGlobal( mWestSouth );
01026         if (!region)
01027         {
01028                 gViewerWindow->alertXml("CannotReleaseLandNoRegion");
01029                 return;
01030         }
01031 
01032         //U32 flags = PR_NONE;
01033         //if (god_force) flags |= PR_GOD_FORCE;
01034 
01035         LLMessageSystem* msg = gMessageSystem;
01036         msg->newMessage("ParcelRelease");
01037         msg->nextBlock("AgentData");
01038         msg->addUUID("AgentID", gAgent.getID() );
01039         msg->addUUID("SessionID", gAgent.getSessionID() );
01040         msg->nextBlock("Data");
01041         msg->addS32("LocalID", mCurrentParcel->getLocalID() );
01042         //msg->addU32("Flags", flags);
01043         msg->sendReliable( region->getHost() );
01044 
01045         // Blitz selection, since the parcel might be non-rectangular, and
01046         // we won't have appropriate parcel information.
01047         deselectLand();
01048 }
01049 
01050 class LLViewerParcelMgr::ParcelBuyInfo
01051 {
01052 public:
01053         LLUUID  mAgent;
01054         LLUUID  mSession;
01055         LLUUID  mGroup;
01056         BOOL    mIsGroupOwned;
01057         BOOL    mRemoveContribution;
01058         BOOL    mIsClaim;
01059         LLHost  mHost;
01060         
01061         // for parcel buys
01062         S32             mParcelID;
01063         S32             mPrice;
01064         S32             mArea;
01065 
01066         // for land claims
01067         F32             mWest;
01068         F32             mSouth;
01069         F32             mEast;
01070         F32             mNorth;
01071 };
01072 
01073 LLViewerParcelMgr::ParcelBuyInfo* LLViewerParcelMgr::setupParcelBuy(
01074         const LLUUID& agent_id,
01075         const LLUUID& session_id,
01076         const LLUUID& group_id,
01077         BOOL is_group_owned,
01078         BOOL is_claim,
01079         BOOL remove_contribution)
01080 {
01081         if (!mSelected || !mCurrentParcel)
01082         {
01083                 gViewerWindow->alertXml("CannotBuyLandNothingSelected");
01084                 return NULL;
01085         }
01086 
01087         LLViewerRegion *region = gWorldp->getRegionFromPosGlobal( mWestSouth );
01088         if (!region)
01089         {
01090                 gViewerWindow->alertXml("CannotBuyLandNoRegion");
01091                 return NULL;
01092         }
01093         
01094         if (is_claim)
01095         {
01096                 llinfos << "Claiming " << mWestSouth << " to " << mEastNorth << llendl;
01097                 llinfos << "Region " << region->getOriginGlobal() << llendl;
01098 
01099                 // BUG: Only works for the region containing mWestSouthBottom
01100                 LLVector3d east_north_region_check( mEastNorth );
01101                 east_north_region_check.mdV[VX] -= 0.5;
01102                 east_north_region_check.mdV[VY] -= 0.5;
01103 
01104                 LLViewerRegion *region2 = gWorldp->getRegionFromPosGlobal( east_north_region_check );
01105 
01106                 if (region != region2)
01107                 {
01108                         gViewerWindow->alertXml("CantBuyLandAcrossMultipleRegions");
01109                         return NULL;
01110                 }
01111         }
01112         
01113         
01114         ParcelBuyInfo* info = new ParcelBuyInfo;
01115         
01116         info->mAgent = agent_id;
01117         info->mSession = session_id;
01118         info->mGroup = group_id;
01119         info->mIsGroupOwned = is_group_owned;
01120         info->mIsClaim = is_claim;
01121         info->mRemoveContribution = remove_contribution;
01122         info->mHost = region->getHost();
01123         info->mPrice = mCurrentParcel->getSalePrice();
01124         info->mArea = mCurrentParcel->getArea();
01125         
01126         if (!is_claim)
01127         {
01128                 info->mParcelID = mCurrentParcel->getLocalID();
01129         }
01130         else
01131         {
01132                 // BUG: Make work for cross-region selections
01133                 LLVector3 west_south_bottom_region = region->getPosRegionFromGlobal( mWestSouth );
01134                 LLVector3 east_north_top_region = region->getPosRegionFromGlobal( mEastNorth );
01135                 
01136                 info->mWest             = west_south_bottom_region.mV[VX];
01137                 info->mSouth    = west_south_bottom_region.mV[VY];
01138                 info->mEast             = east_north_top_region.mV[VX];
01139                 info->mNorth    = east_north_top_region.mV[VY];
01140         }
01141         
01142         return info;
01143 }
01144 
01145 void LLViewerParcelMgr::sendParcelBuy(ParcelBuyInfo* info)
01146 {
01147         // send the message
01148         LLMessageSystem* msg = gMessageSystem;
01149         msg->newMessage(info->mIsClaim ? "ParcelClaim" : "ParcelBuy");
01150         msg->nextBlock("AgentData");
01151         msg->addUUID("AgentID", info->mAgent);
01152         msg->addUUID("SessionID", info->mSession);
01153         msg->nextBlock("Data");
01154         msg->addUUID("GroupID", info->mGroup);
01155         msg->addBOOL("IsGroupOwned", info->mIsGroupOwned);
01156         if (!info->mIsClaim)
01157         {
01158                 msg->addBOOL("RemoveContribution", info->mRemoveContribution);
01159                 msg->addS32("LocalID", info->mParcelID);
01160         }
01161         msg->addBOOL("Final", TRUE);    // don't allow escrow buys
01162         if (info->mIsClaim)
01163         {
01164                 msg->nextBlock("ParcelData");
01165                 msg->addF32("West",  info->mWest);
01166                 msg->addF32("South", info->mSouth);
01167                 msg->addF32("East",  info->mEast);
01168                 msg->addF32("North", info->mNorth);
01169         }
01170         else // ParcelBuy
01171         {
01172                 msg->nextBlock("ParcelData");
01173                 msg->addS32("Price",info->mPrice);
01174                 msg->addS32("Area",info->mArea);
01175         }
01176         msg->sendReliable(info->mHost);
01177 }
01178 
01179 void LLViewerParcelMgr::deleteParcelBuy(ParcelBuyInfo*& info)
01180 {
01181         delete info;
01182         info = NULL;
01183 }
01184 
01185 void LLViewerParcelMgr::sendParcelDeed(const LLUUID& group_id)
01186 {
01187         if (!mSelected || !mCurrentParcel)
01188         {
01189                 gViewerWindow->alertXml("CannotDeedLandNothingSelected");
01190                 return;
01191         }
01192         if(group_id.isNull())
01193         {
01194                 gViewerWindow->alertXml("CannotDeedLandNoGroup");
01195                 return;
01196         }
01197         LLViewerRegion *region = gWorldp->getRegionFromPosGlobal( mWestSouth );
01198         if (!region)
01199         {
01200                 gViewerWindow->alertXml("CannotDeedLandNoRegion");
01201                 return;
01202         }
01203 
01204         LLMessageSystem* msg = gMessageSystem;
01205         msg->newMessage("ParcelDeedToGroup");
01206         msg->nextBlock("AgentData");
01207         msg->addUUID("AgentID", gAgent.getID() );
01208         msg->addUUID("SessionID", gAgent.getSessionID() );
01209         msg->nextBlock("Data");
01210         msg->addUUID("GroupID", group_id );
01211         msg->addS32("LocalID", mCurrentParcel->getLocalID() );
01212         //msg->addU32("JoinNeighbors", join);
01213         msg->sendReliable( region->getHost() );
01214 }
01215 
01216 
01217 /*
01218 // *NOTE: We cannot easily make landmarks at global positions because
01219 // global positions probably refer to a sim/local combination which
01220 // can move over time. We could implement this by looking up the
01221 // region global x,y, but it's easier to take it out for now.
01222 void LLViewerParcelMgr::makeLandmarkAtSelection()
01223 {
01224         // Don't create for parcels you don't own
01225         if (gAgent.getID() != mCurrentParcel->getOwnerID())
01226         {
01227                 return;
01228         }
01229 
01230         LLVector3d global_center(mWestSouth);
01231         global_center += mEastNorth;
01232         global_center *= 0.5f;
01233 
01234         LLViewerRegion* region;
01235         region = gWorldp->getRegionFromPosGlobal(global_center);
01236 
01237         LLVector3 west_south_bottom_region = region->getPosRegionFromGlobal( mWestSouth );
01238         LLVector3 east_north_top_region = region->getPosRegionFromGlobal( mEastNorth );
01239 
01240         LLString name("My Land");
01241         char buffer[MAX_STRING];
01242         S32 pos_x = (S32)floor((west_south_bottom_region.mV[VX] + east_north_top_region.mV[VX]) / 2.0f);
01243         S32 pos_y = (S32)floor((west_south_bottom_region.mV[VY] + east_north_top_region.mV[VY]) / 2.0f);
01244         sprintf(buffer, "%s in %s (%d, %d)",
01245                         name.c_str(),
01246                         region->getName().c_str(),
01247                         pos_x, pos_y);
01248         name.assign(buffer);
01249 
01250         const char* desc = "Claimed land";
01251         create_landmark(name.c_str(), desc, global_center);
01252 }
01253 */
01254 
01255 const LLString& LLViewerParcelMgr::getAgentParcelName() const
01256 {
01257         return mAgentParcel->getName();
01258 }
01259 
01260 
01261 void LLViewerParcelMgr::sendParcelPropertiesUpdate(LLParcel* parcel)
01262 {
01263         if (!parcel) return;
01264 
01265         LLViewerRegion *region = gWorldp->getRegionFromPosGlobal( mWestSouth );
01266         if (!region) return;
01267 
01268         LLMessageSystem *msg = gMessageSystem;
01269 
01270         msg->newMessageFast(_PREHASH_ParcelPropertiesUpdate);
01271         msg->nextBlockFast(_PREHASH_AgentData);
01272         msg->addUUIDFast(_PREHASH_AgentID,      gAgent.getID() );
01273         msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
01274         msg->nextBlockFast(_PREHASH_ParcelData);
01275         msg->addS32Fast(_PREHASH_LocalID, parcel->getLocalID() );
01276 
01277         U32 flags = 0x0;
01278         // request new properties update from simulator
01279         flags |= 0x01;
01280         msg->addU32("Flags", flags);
01281 
01282         parcel->packMessage(msg);
01283 
01284         msg->sendReliable( region->getHost() );
01285 }
01286 
01287 
01288 void LLViewerParcelMgr::requestHoverParcelProperties(const LLVector3d& pos)
01289 {
01290         LLViewerRegion *region = gWorldp->getRegionFromPosGlobal( pos );
01291         if (!region)
01292         {
01293                 return;
01294         }
01295 
01296         // Send a rectangle around the point.
01297         // This means the parcel sent back is at least a rectangle around the point,
01298         // which is more efficient for public land.  Fewer requests are sent.  JC
01299         LLVector3 wsb_region = region->getPosRegionFromGlobal( pos );
01300 
01301         F32 west  = PARCEL_GRID_STEP_METERS * floor( wsb_region.mV[VX] / PARCEL_GRID_STEP_METERS );
01302         F32 south = PARCEL_GRID_STEP_METERS * floor( wsb_region.mV[VY] / PARCEL_GRID_STEP_METERS );
01303 
01304         F32 east  = west  + PARCEL_GRID_STEP_METERS;
01305         F32 north = south + PARCEL_GRID_STEP_METERS;
01306 
01307         // Send request message
01308         LLMessageSystem *msg = gMessageSystem;
01309         msg->newMessageFast(_PREHASH_ParcelPropertiesRequest);
01310         msg->nextBlockFast(_PREHASH_AgentData);
01311         msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
01312         msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
01313         msg->nextBlockFast(_PREHASH_ParcelData);
01314         msg->addS32Fast(_PREHASH_SequenceID,    HOVERED_PARCEL_SEQ_ID );
01315         msg->addF32Fast(_PREHASH_West,                  west );
01316         msg->addF32Fast(_PREHASH_South,                 south );
01317         msg->addF32Fast(_PREHASH_East,                  east );
01318         msg->addF32Fast(_PREHASH_North,                 north );
01319         msg->addBOOL("SnapSelection",                   FALSE );
01320         msg->sendReliable( region->getHost() );
01321 
01322         mHoverRequestResult = PARCEL_RESULT_NO_DATA;
01323 }
01324 
01325 
01326 // static
01327 void LLViewerParcelMgr::processParcelOverlay(LLMessageSystem *msg, void **user)
01328 {
01329         if (gNoRender)
01330         {
01331                 return;
01332         }
01333 
01334         // Extract the packed overlay information
01335         S32 packed_overlay_size = msg->getSizeFast(_PREHASH_ParcelData, _PREHASH_Data);
01336 
01337         if (packed_overlay_size == 0)
01338         {
01339                 llwarns << "Overlay size 0" << llendl;
01340                 return;
01341         }
01342 
01343         S32 parcels_per_edge = gParcelMgr->mParcelsPerEdge;
01344         S32 expected_size = parcels_per_edge * parcels_per_edge / PARCEL_OVERLAY_CHUNKS;
01345         if (packed_overlay_size != expected_size)
01346         {
01347                 llwarns << "Got parcel overlay size " << packed_overlay_size
01348                         << " expecting " << expected_size << llendl;
01349                 return;
01350         }
01351 
01352         S32 sequence_id;
01353         msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_SequenceID, sequence_id);
01354         msg->getBinaryDataFast(
01355                         _PREHASH_ParcelData,
01356                         _PREHASH_Data,
01357                         sPackedOverlay,
01358                         expected_size);
01359 
01360         LLHost host = msg->getSender();
01361         LLViewerRegion *region = gWorldp->getRegion(host);
01362         if (region)
01363         {
01364                 region->mParcelOverlay->uncompressLandOverlay( sequence_id, sPackedOverlay );
01365         }
01366 }
01367 
01368 
01369 // static
01370 void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **user)
01371 {
01372         S32             request_result;
01373         S32             sequence_id;
01374         BOOL    snap_selection = FALSE;
01375         S32             self_count = 0;
01376         S32             other_count = 0;
01377         S32             public_count = 0;
01378         S32             local_id;
01379         LLUUID  owner_id;
01380         BOOL    is_group_owned;
01381         U32 auction_id = 0;
01382         S32             claim_price_per_meter = 0;
01383         S32             rent_price_per_meter = 0;
01384         S32             claim_date = 0;
01385         LLVector3       aabb_min;
01386         LLVector3       aabb_max;
01387         S32             area = 0;
01388         S32             sw_max_prims = 0;
01389         S32             sw_total_prims = 0;
01390         //LLUUID        buyer_id;
01391         U8 status = 0;
01392         S32             max_prims = 0;
01393         S32             total_prims = 0;
01394         S32             owner_prims = 0;
01395         S32             group_prims = 0;
01396         S32             other_prims = 0;
01397         S32             selected_prims = 0;
01398         F32             parcel_prim_bonus = 1.f;
01399         BOOL    region_push_override = false;
01400         BOOL    region_deny_anonymous_override = false;
01401         BOOL    region_deny_identified_override = false;
01402         BOOL    region_deny_transacted_override = false;
01403 
01404         S32             other_clean_time = 0;
01405 
01406         msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_RequestResult, request_result );
01407         msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_SequenceID, sequence_id );
01408 
01409         if (request_result == PARCEL_RESULT_NO_DATA)
01410         {
01411                 // no valid parcel data
01412                 llinfos << "no valid parcel data" << llendl;
01413                 return;
01414         }
01415 
01416         // Decide where the data will go.
01417         LLParcel* parcel = NULL;
01418         if (sequence_id == SELECTED_PARCEL_SEQ_ID)
01419         {
01420                 // ...selected parcels report this sequence id
01421                 gParcelMgr->mRequestResult = PARCEL_RESULT_SUCCESS;
01422                 parcel = gParcelMgr->mCurrentParcel;
01423         }
01424         else if (sequence_id == HOVERED_PARCEL_SEQ_ID)
01425         {
01426                 gParcelMgr->mHoverRequestResult = PARCEL_RESULT_SUCCESS;
01427                 parcel = gParcelMgr->mHoverParcel;
01428         }
01429         else if (sequence_id == COLLISION_NOT_IN_GROUP_PARCEL_SEQ_ID ||
01430                          sequence_id == COLLISION_NOT_ON_LIST_PARCEL_SEQ_ID ||
01431                          sequence_id == COLLISION_BANNED_PARCEL_SEQ_ID)
01432         {
01433                 gParcelMgr->mHoverRequestResult = PARCEL_RESULT_SUCCESS;
01434                 parcel = gParcelMgr->mCollisionParcel;
01435         }
01436         else if (sequence_id == 0 || sequence_id > gParcelMgr->mAgentParcelSequenceID)
01437         {
01438                 // new agent parcel
01439                 gParcelMgr->mAgentParcelSequenceID = sequence_id;
01440                 parcel = gParcelMgr->mAgentParcel;
01441         }
01442         else
01443         {
01444                 llinfos << "out of order agent parcel sequence id " << sequence_id
01445                         << " last good " << gParcelMgr->mAgentParcelSequenceID
01446                         << llendl;
01447                 return;
01448         }
01449 
01450         msg->getBOOL("ParcelData", "SnapSelection", snap_selection);
01451         msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_SelfCount, self_count);
01452         msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_OtherCount, other_count);
01453         msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_PublicCount, public_count);
01454         msg->getS32Fast( _PREHASH_ParcelData, _PREHASH_LocalID,         local_id );
01455         msg->getUUIDFast(_PREHASH_ParcelData, _PREHASH_OwnerID,         owner_id);
01456         msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_IsGroupOwned, is_group_owned);
01457         msg->getU32Fast(_PREHASH_ParcelData, _PREHASH_AuctionID, auction_id);
01458         msg->getS32Fast( _PREHASH_ParcelData, _PREHASH_ClaimDate,       claim_date);
01459         msg->getS32Fast( _PREHASH_ParcelData, _PREHASH_ClaimPrice,      claim_price_per_meter);
01460         msg->getS32Fast( _PREHASH_ParcelData, _PREHASH_RentPrice,       rent_price_per_meter);
01461         msg->getVector3Fast(_PREHASH_ParcelData, _PREHASH_AABBMin, aabb_min);
01462         msg->getVector3Fast(_PREHASH_ParcelData, _PREHASH_AABBMax, aabb_max);
01463         msg->getS32Fast(        _PREHASH_ParcelData, _PREHASH_Area, area );
01464         //msg->getUUIDFast(     _PREHASH_ParcelData, _PREHASH_BuyerID, buyer_id);
01465         msg->getU8("ParcelData", "Status", status);
01466         msg->getS32("ParcelData", "SimWideMaxPrims", sw_max_prims );
01467         msg->getS32("ParcelData", "SimWideTotalPrims", sw_total_prims );
01468         msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_MaxPrims, max_prims );
01469         msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_TotalPrims, total_prims );
01470         msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_OwnerPrims, owner_prims );
01471         msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_GroupPrims, group_prims );
01472         msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_OtherPrims, other_prims );
01473         msg->getS32Fast(_PREHASH_ParcelData, _PREHASH_SelectedPrims, selected_prims );
01474         msg->getF32Fast(_PREHASH_ParcelData, _PREHASH_ParcelPrimBonus, parcel_prim_bonus );
01475         msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_RegionPushOverride, region_push_override );
01476         msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_RegionDenyAnonymous, region_deny_anonymous_override );
01477         msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_RegionDenyIdentified, region_deny_identified_override );
01478         msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_RegionDenyTransacted, region_deny_transacted_override );
01479 
01480         msg->getS32("ParcelData", "OtherCleanTime", other_clean_time );
01481 
01482         // Actually extract the data.
01483         if (parcel)
01484         {
01485                 parcel->init(owner_id,
01486                         FALSE, FALSE, FALSE,
01487                         claim_date, claim_price_per_meter, rent_price_per_meter,
01488                         area, other_prims, parcel_prim_bonus, is_group_owned);
01489                 parcel->setLocalID(local_id);
01490                 parcel->setAABBMin(aabb_min);
01491                 parcel->setAABBMax(aabb_max);
01492 
01493                 parcel->setAuctionID(auction_id);
01494                 parcel->setOwnershipStatus((LLParcel::EOwnershipStatus)status);
01495 
01496                 parcel->setSimWideMaxPrimCapacity(sw_max_prims);
01497                 parcel->setSimWidePrimCount(sw_total_prims);
01498                 parcel->setMaxPrimCapacity(max_prims);
01499                 parcel->setOwnerPrimCount(owner_prims);
01500                 parcel->setGroupPrimCount(group_prims);
01501                 parcel->setOtherPrimCount(other_prims);
01502                 parcel->setSelectedPrimCount(selected_prims);
01503                 parcel->setParcelPrimBonus(parcel_prim_bonus);
01504 
01505                 parcel->setCleanOtherTime(other_clean_time);
01506                 parcel->setRegionPushOverride(region_push_override);
01507                 parcel->setRegionDenyAnonymousOverride(region_deny_anonymous_override);
01508                 parcel->setRegionDenyIdentifiedOverride(region_deny_identified_override);
01509                 parcel->setRegionDenyTransactedOverride(region_deny_transacted_override);
01510                 parcel->unpackMessage(msg);
01511 
01512                 if (parcel == gParcelMgr->mAgentParcel)
01513                 {
01514                         S32 bitmap_size =       gParcelMgr->mParcelsPerEdge
01515                                                                 * gParcelMgr->mParcelsPerEdge
01516                                                                 / 8;
01517                         U8* bitmap = new U8[ bitmap_size ];
01518                         msg->getBinaryDataFast(_PREHASH_ParcelData, _PREHASH_Bitmap, bitmap, bitmap_size);
01519 
01520                         gParcelMgr->writeAgentParcelFromBitmap(bitmap);
01521                         delete[] bitmap;
01522                 }
01523         }
01524 
01525         // Handle updating selections, if necessary.
01526         if (sequence_id == SELECTED_PARCEL_SEQ_ID)
01527         {
01528                 // Update selected counts
01529                 gParcelMgr->mCurrentParcelSelection->mSelectedSelfCount = self_count;
01530                 gParcelMgr->mCurrentParcelSelection->mSelectedOtherCount = other_count;
01531                 gParcelMgr->mCurrentParcelSelection->mSelectedPublicCount = public_count;
01532 
01533                 gParcelMgr->mCurrentParcelSelection->mSelectedMultipleOwners =
01534                                                         (request_result == PARCEL_RESULT_MULTIPLE);
01535 
01536                 // Select the whole parcel
01537                 LLViewerRegion *region = gWorldp->getRegion( msg->getSender() );
01538                 if (region)
01539                 {
01540                         if (!snap_selection)
01541                         {
01542                                 // don't muck with the westsouth and eastnorth.
01543                                 // just highlight it
01544                                 LLVector3 west_south = region->getPosRegionFromGlobal(gParcelMgr->mWestSouth);
01545                                 LLVector3 east_north = region->getPosRegionFromGlobal(gParcelMgr->mEastNorth);
01546 
01547                                 gParcelMgr->resetSegments(gParcelMgr->mHighlightSegments);
01548                                 gParcelMgr->writeHighlightSegments(
01549                                                                 west_south.mV[VX],
01550                                                                 west_south.mV[VY],
01551                                                                 east_north.mV[VX],
01552                                                                 east_north.mV[VY] );
01553                                 gParcelMgr->mCurrentParcelSelection->mWholeParcelSelected = FALSE;
01554                         }
01555                         else if (0 == local_id)
01556                         {
01557                                 // this is public land, just highlight the selection
01558                                 gParcelMgr->mWestSouth = region->getPosGlobalFromRegion( aabb_min );
01559                                 gParcelMgr->mEastNorth = region->getPosGlobalFromRegion( aabb_max );
01560 
01561                                 gParcelMgr->resetSegments(gParcelMgr->mHighlightSegments);
01562                                 gParcelMgr->writeHighlightSegments(
01563                                                                 aabb_min.mV[VX],
01564                                                                 aabb_min.mV[VY],
01565                                                                 aabb_max.mV[VX],
01566                                                                 aabb_max.mV[VY] );
01567                                 gParcelMgr->mCurrentParcelSelection->mWholeParcelSelected = TRUE;
01568                         }
01569                         else
01570                         {
01571                                 gParcelMgr->mWestSouth = region->getPosGlobalFromRegion( aabb_min );
01572                                 gParcelMgr->mEastNorth = region->getPosGlobalFromRegion( aabb_max );
01573 
01574                                 // Owned land, highlight the boundaries
01575                                 S32 bitmap_size =       gParcelMgr->mParcelsPerEdge
01576                                                                         * gParcelMgr->mParcelsPerEdge
01577                                                                         / 8;
01578                                 U8* bitmap = new U8[ bitmap_size ];
01579                                 msg->getBinaryDataFast(_PREHASH_ParcelData, _PREHASH_Bitmap, bitmap, bitmap_size);
01580 
01581                                 gParcelMgr->resetSegments(gParcelMgr->mHighlightSegments);
01582                                 gParcelMgr->writeSegmentsFromBitmap( bitmap, gParcelMgr->mHighlightSegments );
01583 
01584                                 delete[] bitmap;
01585                                 bitmap = NULL;
01586 
01587                                 gParcelMgr->mCurrentParcelSelection->mWholeParcelSelected = TRUE;
01588                         }
01589 
01590                         // Request access list information for this land
01591                         gParcelMgr->sendParcelAccessListRequest(AL_ACCESS | AL_BAN);
01592 
01593                         // Request dwell for this land, if it's not public land.
01594                         gParcelMgr->mSelectedDwell = 0.f;
01595                         if (0 != local_id)
01596                         {
01597                                 gParcelMgr->sendParcelDwellRequest();
01598                         }
01599 
01600                         gParcelMgr->mSelected = TRUE;
01601                         gParcelMgr->notifyObservers();
01602                 }
01603         }
01604         else if (sequence_id == COLLISION_NOT_IN_GROUP_PARCEL_SEQ_ID ||
01605                          sequence_id == COLLISION_NOT_ON_LIST_PARCEL_SEQ_ID  ||
01606                          sequence_id == COLLISION_BANNED_PARCEL_SEQ_ID)
01607         {
01608                 // We're about to collide with this parcel
01609                 gParcelMgr->mRenderCollision = TRUE;
01610                 gParcelMgr->mCollisionTimer.reset();
01611 
01612                 // Differentiate this parcel if we are banned from it.
01613                 if (sequence_id == COLLISION_BANNED_PARCEL_SEQ_ID)
01614                 {
01615                         gParcelMgr->mCollisionBanned = BA_BANNED;
01616                 }
01617                 else if (sequence_id == COLLISION_NOT_IN_GROUP_PARCEL_SEQ_ID)
01618                 {
01619                         gParcelMgr->mCollisionBanned = BA_NOT_IN_GROUP;
01620                 }
01621                 else 
01622                 {
01623                         gParcelMgr->mCollisionBanned = BA_NOT_ON_LIST;
01624 
01625                 }
01626 
01627                 S32 bitmap_size =       gParcelMgr->mParcelsPerEdge
01628                                                         * gParcelMgr->mParcelsPerEdge
01629                                                         / 8;
01630                 U8* bitmap = new U8[ bitmap_size ];
01631                 msg->getBinaryDataFast(_PREHASH_ParcelData, _PREHASH_Bitmap, bitmap, bitmap_size);
01632 
01633                 gParcelMgr->resetSegments(gParcelMgr->mCollisionSegments);
01634                 gParcelMgr->writeSegmentsFromBitmap( bitmap, gParcelMgr->mCollisionSegments );
01635 
01636                 delete[] bitmap;
01637                 bitmap = NULL;
01638 
01639         }
01640         else if (sequence_id == HOVERED_PARCEL_SEQ_ID)
01641         {
01642                 LLViewerRegion *region = gWorldp->getRegion( msg->getSender() );
01643                 if (region)
01644                 {
01645                         gParcelMgr->mHoverWestSouth = region->getPosGlobalFromRegion( aabb_min );
01646                         gParcelMgr->mHoverEastNorth = region->getPosGlobalFromRegion( aabb_max );
01647                 }
01648                 else
01649                 {
01650                         gParcelMgr->mHoverWestSouth.clearVec();
01651                         gParcelMgr->mHoverEastNorth.clearVec();
01652                 }
01653         }
01654         else
01655         {
01656                 // It's the agent parcel
01657                 BOOL new_parcel = parcel ? FALSE : TRUE;
01658                 if (parcel)
01659                 {
01660                         S32 parcelid = parcel->getLocalID();
01661                         U64 regionid = gAgent.getRegion()->getHandle();
01662                         if (parcelid != gParcelMgr->mMediaParcelId || regionid != gParcelMgr->mMediaRegionId)
01663                         {
01664                                 gParcelMgr->mMediaParcelId = parcelid;
01665                                 gParcelMgr->mMediaRegionId = regionid;
01666                                 new_parcel = TRUE;
01667                         }
01668                 }
01669                 // look for music.
01670                 if (gAudiop)
01671                 {
01672                         if (parcel)
01673                         {
01674                                 LLString music_url_raw = parcel->getMusicURL();
01675 
01676                                 // Trim off whitespace from front and back
01677                                 LLString music_url = music_url_raw;
01678                                 LLString::trim(music_url);
01679 
01680                                 // On entering a new parcel, stop the last stream if the
01681                                 // new parcel has a different music url.  (Empty URL counts
01682                                 // as different.)
01683                                 const char* stream_url = gAudiop->getInternetStreamURL();
01684 
01685                                 if (music_url.empty() || music_url != stream_url)
01686                                 {
01687                                         // URL is different from one currently playing.
01688                                         gAudiop->stopInternetStream();
01689 
01690                                         // If there is a new music URL and it's valid, play it.
01691                                         if (music_url.size() > 12)
01692                                         {
01693                                                 if (music_url.substr(0,7) == "http://")
01694                                                 {
01695                                                         optionally_start_music(music_url);
01696                                                 }
01697                                         }
01698                                         else if (gAudiop->getInternetStreamURL()[0])
01699                                         {
01700                                                 llinfos << "Stopping parcel music" << llendl;
01701                                                 gAudiop->startInternetStream(NULL);
01702                                         }
01703                                 }
01704                         }
01705                         else
01706                         {
01707                                 // Public land has no music
01708                                 gAudiop->stopInternetStream();
01709                         }
01710                 }//if gAudiop
01711 
01712                 // now check for video
01713                 if (LLMediaEngine::getInstance ()->isAvailable ())
01714                 {
01715                         // we have a player
01716                         if (parcel)
01717                         {
01718                                 // we're in a parcel
01719                                 std::string mediaUrl = std::string ( parcel->getMediaURL () );
01720                                 LLString::trim(mediaUrl);
01721 
01722                                 // something changed
01723                                 LLMediaEngine* me = LLMediaEngine::getInstance();
01724                                 if (  ( me->getUrl () != mediaUrl )
01725                                         || ( me->getImageUUID () != parcel->getMediaID () ) 
01726                                         || ( me->isAutoScaled () != parcel->getMediaAutoScale () ) )
01727                                 {
01728                                         BOOL video_was_playing = FALSE;
01729                                         LLMediaBase* renderer = me->getMediaRenderer();
01730                                         if (renderer && (renderer->isPlaying() || renderer->isLooping()))
01731                                         {
01732                                                 video_was_playing = TRUE;
01733                                         }
01734 
01735                                         stop_video();
01736 
01737                                         if ( !mediaUrl.empty () )
01738                                         {
01739                                                 // Someone has "changed the channel", changing the URL of a video
01740                                                 // you were already watching.  Do we want to automatically start playing? JC
01741                                                 if (!new_parcel
01742                                                         && gSavedSettings.getBOOL("AudioStreamingVideo")
01743                                                         && video_was_playing)
01744                                                 {
01745                                                         start_video(parcel);
01746                                                 }
01747                                                 else
01748                                                 {
01749                                                         // "Prepare" the media engine, but don't auto-play. JC
01750                                                         optionally_prepare_video(parcel);
01751                                                 }
01752                                         }
01753                                 }
01754                         }
01755                         else
01756                         {
01757                                 stop_video();
01758                         }
01759                 }
01760                 else
01761                 {
01762                         // no audio player, do a first use dialog if their is media here
01763                         if (parcel)
01764                         {
01765                                 std::string mediaUrl = std::string ( parcel->getMediaURL () );
01766                                 if (!mediaUrl.empty ())
01767                                 {
01768                                         if (gSavedSettings.getWarning("QuickTimeInstalled"))
01769                                         {
01770                                                 gSavedSettings.setWarning("QuickTimeInstalled", FALSE);
01771 
01772                                                 LLNotifyBox::showXml("NoQuickTime" );
01773                                         };
01774                                 }
01775                         }
01776                 }
01777 
01778         };
01779 }
01780 
01781 void optionally_start_music(const LLString& music_url)
01782 {
01783         if (gSavedSettings.getWarning("FirstStreamingMusic"))
01784         {
01785                 std::string* newstring = new std::string(music_url);
01786                 gViewerWindow->alertXml("ParcelCanPlayMusic",
01787                         callback_start_music,
01788                         (void*)newstring);
01789 
01790         }
01791         else if (gSavedSettings.getBOOL("AudioStreamingMusic"))
01792         {
01793                 // Make the user click the start button on the overlay bar. JC
01794                 //              llinfos << "Starting parcel music " << music_url << llendl;
01795 
01796                 // now only play music when you enter a new parcel if the control is in PLAY state
01797                 // changed as part of SL-4878
01798                 if ( gOverlayBar && gOverlayBar->musicPlaying() )
01799                 {
01800                         LLOverlayBar::musicPlay(NULL);
01801                 }
01802         }
01803 }
01804 
01805 
01806 void callback_start_music(S32 option, void* data)
01807 {
01808         std::string* music_url = (std::string*)data;
01809 
01810         if (0 == option)
01811         {
01812                 gSavedSettings.setBOOL("AudioStreamingMusic", TRUE);
01813                 llinfos << "Starting first parcel music " << music_url << llendl;
01814                 LLOverlayBar::musicPlay(NULL);
01815         }
01816         else
01817         {
01818                 gSavedSettings.setBOOL("AudioStreamingMusic", FALSE);
01819         }
01820 
01821         gSavedSettings.setWarning("FirstStreamingMusic", FALSE);
01822 
01823         delete music_url;
01824         music_url = NULL;
01825 }
01826 
01827 void prepare_video(const LLParcel *parcel)
01828 {
01829         std::string mediaUrl;
01830         if (parcel->getParcelFlag(PF_URL_RAW_HTML))
01831         {
01832                 mediaUrl = std::string("data:");
01833                 mediaUrl.append(parcel->getMediaURL());
01834         }
01835         else
01836         {
01837                 mediaUrl = std::string ( parcel->getMediaURL () );
01838         }
01839         LLMediaEngine::getInstance ()->setUrl ( mediaUrl );
01840         LLMediaEngine::getInstance ()->setImageUUID ( parcel->getMediaID () );
01841         LLMediaEngine::getInstance ()->setAutoScaled ( parcel->getMediaAutoScale () ? TRUE : FALSE );  // (U8 instead of BOOL for future expansion)
01842 }
01843 
01844 void start_video(const LLParcel *parcel)
01845 {
01846         prepare_video(parcel);
01847         std::string path( "" );
01848         LLMediaEngine::getInstance ()->convertImageAndLoadUrl ( true, false, path);
01849 }
01850 
01851 void stop_video()
01852 {
01853         // set up remote control so stop is selected
01854         LLMediaEngine::getInstance ()->stop ();
01855         if (gOverlayBar)
01856         {
01857                 gOverlayBar->refresh ();
01858         }
01859 
01860         if (LLMediaEngine::getInstance ()->isLoaded())
01861         {
01862                 LLMediaEngine::getInstance ()->unload ();
01863 
01864                 gImageList.updateMovieImage(LLUUID::null, FALSE);
01865                 gCurrentMovieID.setNull();
01866         }
01867 
01868         LLMediaEngine::getInstance ()->setUrl ( "" );
01869         LLMediaEngine::getInstance ()->setImageUUID ( LLUUID::null );
01870         
01871 }
01872 
01873 void optionally_prepare_video(const LLParcel *parcelp)
01874 {
01875         if (gSavedSettings.getWarning("FirstStreamingVideo"))
01876         {
01877                 gViewerWindow->alertXml("ParcelCanPlayMedia",
01878                         callback_prepare_video,
01879                         (void*)parcelp);
01880         }
01881         else
01882         {
01883                 llinfos << "Entering parcel " << parcelp->getLocalID() << " with video " <<  parcelp->getMediaURL() << llendl;
01884                 prepare_video(parcelp);
01885         }
01886 }
01887 
01888 
01889 void callback_prepare_video(S32 option, void* data)
01890 {
01891         const LLParcel *parcelp = (const LLParcel *)data;
01892 
01893         if (0 == option)
01894         {
01895                 gSavedSettings.setBOOL("AudioStreamingVideo", TRUE);
01896                 llinfos << "Starting parcel video " <<  parcelp->getMediaURL() << " on parcel " << parcelp->getLocalID() << llendl;
01897                 gMessageSystem->setHandlerFunc("ParcelMediaCommandMessage", LLMediaEngine::process_parcel_media);
01898                 gMessageSystem->setHandlerFunc ( "ParcelMediaUpdate", LLMediaEngine::process_parcel_media_update );
01899                 prepare_video(parcelp);
01900         }
01901         else
01902         {
01903                 gMessageSystem->setHandlerFunc("ParcelMediaCommandMessage", null_message_callback);
01904                 gMessageSystem->setHandlerFunc ( "ParcelMediaUpdate", null_message_callback );
01905                 gSavedSettings.setBOOL("AudioStreamingVideo", FALSE);
01906         }
01907 
01908         gSavedSettings.setWarning("FirstStreamingVideo", FALSE);
01909 }
01910 
01911 // static
01912 void LLViewerParcelMgr::processParcelAccessListReply(LLMessageSystem *msg, void **user)
01913 {
01914         LLUUID agent_id;
01915         S32 sequence_id = 0;
01916         U32 message_flags = 0x0;
01917         S32 parcel_id = -1;
01918 
01919         msg->getUUIDFast(_PREHASH_Data, _PREHASH_AgentID, agent_id);
01920         msg->getS32Fast( _PREHASH_Data, _PREHASH_SequenceID, sequence_id );     //ignored
01921         msg->getU32Fast( _PREHASH_Data, _PREHASH_Flags, message_flags);
01922         msg->getS32Fast( _PREHASH_Data, _PREHASH_LocalID, parcel_id);
01923 
01924         LLParcel* parcel = gParcelMgr->mCurrentParcel;
01925         if (!parcel) return;
01926 
01927         if (parcel_id != parcel->getLocalID())
01928         {
01929                 llwarns << "processParcelAccessListReply for parcel " << parcel_id
01930                         << " which isn't the selected parcel " << parcel->getLocalID()<< llendl;
01931                 return;
01932         }
01933 
01934         if (message_flags & AL_ACCESS)
01935         {
01936                 parcel->unpackAccessEntries(msg, &(parcel->mAccessList) );
01937         }
01938         else if (message_flags & AL_BAN)
01939         {
01940                 parcel->unpackAccessEntries(msg, &(parcel->mBanList) );
01941         }
01942         /*else if (message_flags & AL_RENTER)
01943         {
01944                 parcel->unpackAccessEntries(msg, &(parcel->mRenterList) );
01945         }*/
01946 
01947         gParcelMgr->notifyObservers();
01948 }
01949 
01950 
01951 // static
01952 void LLViewerParcelMgr::processParcelDwellReply(LLMessageSystem* msg, void**)
01953 {
01954         LLUUID agent_id;
01955         msg->getUUID("AgentData", "AgentID", agent_id);
01956 
01957         S32 local_id;
01958         msg->getS32("Data", "LocalID", local_id);
01959 
01960         LLUUID parcel_id;
01961         msg->getUUID("Data", "ParcelID", parcel_id);
01962 
01963         F32 dwell;
01964         msg->getF32("Data", "Dwell", dwell);
01965 
01966         if (local_id == gParcelMgr->mCurrentParcel->getLocalID())
01967         {
01968                 gParcelMgr->mSelectedDwell = dwell;
01969                 gParcelMgr->notifyObservers();
01970         }
01971 }
01972 
01973 
01974 void LLViewerParcelMgr::sendParcelAccessListUpdate(U32 which)
01975 {
01976 
01977         LLUUID transactionUUID;
01978         transactionUUID.generate();
01979 
01980         if (!mSelected)
01981         {
01982                 return;
01983         }
01984 
01985         LLViewerRegion *region = gWorldp->getRegionFromPosGlobal( mWestSouth );
01986         if (!region) return;
01987 
01988         LLMessageSystem* msg = gMessageSystem;
01989 
01990         LLParcel* parcel = mCurrentParcel;
01991         if (!parcel) return;
01992 
01993         if (which & AL_ACCESS)
01994         {       
01995                 S32 count = parcel->mAccessList.size();
01996                 S32 num_sections = (S32) ceil(count/PARCEL_MAX_ENTRIES_PER_PACKET);
01997                 S32 sequence_id = 1;
01998                 BOOL start_message = TRUE;
01999                 BOOL initial = TRUE;
02000 
02001                 access_map_const_iterator cit = parcel->mAccessList.begin();
02002                 access_map_const_iterator end = parcel->mAccessList.end();
02003                 while ( (cit != end) || initial ) 
02004                 {       
02005                         if (start_message) 
02006                         {
02007                                 msg->newMessageFast(_PREHASH_ParcelAccessListUpdate);
02008                                 msg->nextBlockFast(_PREHASH_AgentData);
02009                                 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
02010                                 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
02011                                 msg->nextBlockFast(_PREHASH_Data);
02012                                 msg->addU32Fast(_PREHASH_Flags, AL_ACCESS);
02013                                 msg->addS32(_PREHASH_LocalID, parcel->getLocalID() );
02014                                 msg->addUUIDFast(_PREHASH_TransactionID, transactionUUID);
02015                                 msg->addS32Fast(_PREHASH_SequenceID, sequence_id);
02016                                 msg->addS32Fast(_PREHASH_Sections, num_sections);
02017                                 start_message = FALSE;
02018 
02019                                 if (initial && (cit == end))
02020                                 {
02021                                         // pack an empty block if there will be no data
02022                                         msg->nextBlockFast(_PREHASH_List);
02023                                         msg->addUUIDFast(_PREHASH_ID,  LLUUID::null );
02024                                         msg->addS32Fast(_PREHASH_Time, 0 );
02025                                         msg->addU32Fast(_PREHASH_Flags, 0 );
02026                                 }
02027 
02028                                 initial = FALSE;
02029                                 sequence_id++;
02030 
02031                         }
02032                         
02033                         while ( (cit != end) && (msg->getCurrentSendTotal() < MTUBYTES)) 
02034                         {
02035 
02036                                 const LLAccessEntry& entry = (*cit).second;
02037                                 
02038                                 msg->nextBlockFast(_PREHASH_List);
02039                                 msg->addUUIDFast(_PREHASH_ID,  entry.mID );
02040                                 msg->addS32Fast(_PREHASH_Time, entry.mTime );
02041                                 msg->addU32Fast(_PREHASH_Flags, entry.mFlags );
02042                                 ++cit;
02043                         }
02044 
02045                         start_message = TRUE;
02046                         msg->sendReliable( region->getHost() );
02047                 }
02048         }
02049 
02050         if (which & AL_BAN)
02051         {       
02052                 S32 count = parcel->mBanList.size();
02053                 S32 num_sections = (S32) ceil(count/PARCEL_MAX_ENTRIES_PER_PACKET);
02054                 S32 sequence_id = 1;
02055                 BOOL start_message = TRUE;
02056                 BOOL initial = TRUE;
02057 
02058                 access_map_const_iterator cit = parcel->mBanList.begin();
02059                 access_map_const_iterator end = parcel->mBanList.end();
02060                 while ( (cit != end) || initial ) 
02061                 {
02062                         if (start_message) 
02063                         {
02064                                 msg->newMessageFast(_PREHASH_ParcelAccessListUpdate);
02065                                 msg->nextBlockFast(_PREHASH_AgentData);
02066                                 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
02067                                 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
02068                                 msg->nextBlockFast(_PREHASH_Data);
02069                                 msg->addU32Fast(_PREHASH_Flags, AL_BAN);
02070                                 msg->addS32(_PREHASH_LocalID, parcel->getLocalID() );
02071                                 msg->addUUIDFast(_PREHASH_TransactionID, transactionUUID);
02072                                 msg->addS32Fast(_PREHASH_SequenceID, sequence_id);
02073                                 msg->addS32Fast(_PREHASH_Sections, num_sections);
02074                                 start_message = FALSE;
02075 
02076                                 if (initial && (cit == end))
02077                                 {
02078                                         // pack an empty block if there will be no data
02079                                         msg->nextBlockFast(_PREHASH_List);
02080                                         msg->addUUIDFast(_PREHASH_ID,  LLUUID::null );
02081                                         msg->addS32Fast(_PREHASH_Time, 0 );
02082                                         msg->addU32Fast(_PREHASH_Flags, 0 );
02083                                 }
02084 
02085                                 initial = FALSE;
02086                                 sequence_id++;
02087 
02088                         }
02089                         
02090                         while ( (cit != end) && (msg->getCurrentSendTotal() < MTUBYTES)) 
02091                         {
02092                                 const LLAccessEntry& entry = (*cit).second;
02093                                 
02094                                 msg->nextBlockFast(_PREHASH_List);
02095                                 msg->addUUIDFast(_PREHASH_ID,  entry.mID );
02096                                 msg->addS32Fast(_PREHASH_Time, entry.mTime );
02097                                 msg->addU32Fast(_PREHASH_Flags, entry.mFlags );
02098                                 ++cit;
02099                         }
02100 
02101                         start_message = TRUE;
02102                         msg->sendReliable( region->getHost() );
02103                 }
02104         }
02105 }
02106 
02107 
02108 void LLViewerParcelMgr::deedLandToGroup()
02109 {
02110         char group_name[MAX_STRING];            /* Flawfinder: ignore */
02111         gCacheName->getGroupName(mCurrentParcel->getGroupID(), group_name);
02112         LLString::format_map_t args;
02113         args["[AREA]"] = llformat("%d", mCurrentParcel->getArea());
02114         args["[GROUP_NAME]"] = group_name;
02115         if(mCurrentParcel->getContributeWithDeed())
02116         {
02117                 char first_name[DB_FIRST_NAME_BUF_SIZE];                /* Flawfinder: ignore */
02118                 first_name[0] = '\0';
02119                 char last_name[DB_FIRST_NAME_BUF_SIZE];         /* Flawfinder: ignore */
02120                 last_name[0] = '\0';            
02121                 gCacheName->getName(mCurrentParcel->getOwnerID(), first_name, last_name);
02122                 args["[FIRST_NAME]"] = first_name;
02123                 args["[LAST_NAME]"] = last_name;
02124                 gViewerWindow->alertXml("DeedLandToGroupWithContribution",args, deedAlertCB, NULL);
02125         }
02126         else
02127         {
02128                 gViewerWindow->alertXml("DeedLandToGroup",args, deedAlertCB, NULL);
02129         }
02130 }
02131 
02132 // static
02133 void LLViewerParcelMgr::deedAlertCB(S32 option, void*)
02134 {
02135         if (option == 0)
02136         {
02137                 LLParcel* parcel = gParcelMgr->getParcelSelection()->getParcel();
02138                 LLUUID group_id;
02139                 if(parcel)
02140                 {
02141                         group_id = parcel->getGroupID();
02142                 }
02143                 gParcelMgr->sendParcelDeed(group_id);
02144         }
02145 }
02146 
02147 
02148 void LLViewerParcelMgr::startReleaseLand()
02149 {
02150         if (!mSelected)
02151         {
02152                 gViewerWindow->alertXml("CannotReleaseLandNothingSelected");
02153                 return;
02154         }
02155 
02156         if (mRequestResult == PARCEL_RESULT_NO_DATA)
02157         {
02158                 gViewerWindow->alertXml("CannotReleaseLandWatingForServer");
02159                 return;
02160         }
02161 
02162         if (mRequestResult == PARCEL_RESULT_MULTIPLE)
02163         {
02164                 gViewerWindow->alertXml("CannotReleaseLandSelected");
02165                 return;
02166         }
02167 
02168         if (!isParcelOwnedByAgent(mCurrentParcel, GP_LAND_RELEASE)
02169                 && !(gAgent.canManageEstate()))
02170         {
02171                 gViewerWindow->alertXml("CannotReleaseLandDontOwn");
02172                 return;
02173         }
02174 
02175         LLVector3d parcel_center = (mWestSouth + mEastNorth) / 2.0;
02176         LLViewerRegion* region = gWorldp->getRegionFromPosGlobal(parcel_center);
02177         if (!region)
02178         {
02179                 gViewerWindow->alertXml("CannotReleaseLandRegionNotFound");
02180                 return;
02181         }
02182 /*
02183         if ((region->getRegionFlags() & REGION_FLAGS_BLOCK_LAND_RESELL)
02184                 && !gAgent.isGodlike())
02185         {
02186                 LLStringBase<char>::format_map_t args;
02187                 args["[REGION]"] = region->getName();
02188                 gViewerWindow->alertXml("CannotReleaseLandNoTransfer", args);
02189                 return;
02190         }
02191 */
02192 
02193         if (!mCurrentParcelSelection->mWholeParcelSelected)
02194         {
02195                 gViewerWindow->alertXml("CannotReleaseLandPartialSelection");
02196                 return;
02197         }
02198 
02199         // Compute claim price
02200         LLStringBase<char>::format_map_t args;
02201         args["[AREA]"] = llformat("%d",mCurrentParcel->getArea());
02202         gViewerWindow->alertXml("ReleaseLandWarning", args,
02203                                 releaseAlertCB, this);
02204 }
02205 
02206 bool LLViewerParcelMgr::canAgentBuyParcel(LLParcel* parcel, bool forGroup) const
02207 {
02208         if (!parcel)
02209         {
02210                 return false;
02211         }
02212         
02213         if (mSelected  &&  parcel == mCurrentParcel)
02214         {
02215                 if (mRequestResult == PARCEL_RESULT_NO_DATA)
02216                 {
02217                         return false;
02218                 }
02219         }
02220         
02221         const LLUUID& parcelOwner = parcel->getOwnerID();
02222         const LLUUID& authorizeBuyer = parcel->getAuthorizedBuyerID();
02223 
02224         if (parcel->isPublic())
02225         {
02226                 return true;    // change this if want to make it gods only
02227         }
02228         
02229         bool isForSale = parcel->getForSale()
02230                         && ((parcel->getSalePrice() > 0) || (authorizeBuyer.notNull()));
02231                         
02232         bool isEmpowered
02233                 = forGroup ? gAgent.hasPowerInActiveGroup(GP_LAND_DEED) == TRUE : true;
02234                 
02235         bool isOwner
02236                 = parcelOwner == (forGroup ? gAgent.getGroupID() : gAgent.getID());
02237         
02238         bool isAuthorized
02239                 = (authorizeBuyer.isNull() || (gAgent.getID() == authorizeBuyer));
02240         
02241         return isForSale && !isOwner && isAuthorized  && isEmpowered;
02242 }
02243 
02244 
02245 void LLViewerParcelMgr::startBuyLand(BOOL is_for_group)
02246 {
02247         LLFloaterBuyLand::buyLand(getSelectionRegion(), mCurrentParcelSelection, is_for_group == TRUE);
02248 }
02249 
02250 void LLViewerParcelMgr::startSellLand()
02251 {
02252         LLFloaterSellLand::sellLand(getSelectionRegion(), mCurrentParcelSelection);
02253 }
02254 
02255 void LLViewerParcelMgr::startDivideLand()
02256 {
02257         if (!mSelected)
02258         {
02259                 gViewerWindow->alertXml("CannotDivideLandNothingSelected");
02260                 return;
02261         }
02262 
02263         if (mCurrentParcelSelection->mWholeParcelSelected)
02264         {
02265                 gViewerWindow->alertXml("CannotDivideLandPartialSelection");
02266                 return;
02267         }
02268 
02269         gViewerWindow->alertXml("LandDivideWarning", 
02270                 callbackDivideLand,
02271                 this);
02272 }
02273 
02274 // static
02275 void LLViewerParcelMgr::callbackDivideLand(S32 option, void* data)
02276 {
02277         LLViewerParcelMgr* self = (LLViewerParcelMgr*)data;
02278 
02279         LLVector3d parcel_center = (self->mWestSouth + self->mEastNorth) / 2.0;
02280         LLViewerRegion* region = gWorldp->getRegionFromPosGlobal(parcel_center);
02281         if (!region)
02282         {
02283                 gViewerWindow->alertXml("CannotDivideLandNoRegion");
02284                 return;
02285         }
02286 
02287         if (0 == option)
02288         {
02289                 LLVector3 west_south = region->getPosRegionFromGlobal(self->mWestSouth);
02290                 LLVector3 east_north = region->getPosRegionFromGlobal(self->mEastNorth);
02291 
02292                 LLMessageSystem* msg = gMessageSystem;
02293                 msg->newMessage("ParcelDivide");
02294                 msg->nextBlock("AgentData");
02295                 msg->addUUID("AgentID", gAgent.getID());
02296                 msg->addUUID("SessionID", gAgent.getSessionID());
02297                 msg->nextBlock("ParcelData");
02298                 msg->addF32("West", west_south.mV[VX]);
02299                 msg->addF32("South", west_south.mV[VY]);
02300                 msg->addF32("East", east_north.mV[VX]);
02301                 msg->addF32("North", east_north.mV[VY]);
02302                 msg->sendReliable(region->getHost());
02303         }
02304 }
02305 
02306 
02307 void LLViewerParcelMgr::startJoinLand()
02308 {
02309         if (!mSelected)
02310         {
02311                 gViewerWindow->alertXml("CannotJoinLandNothingSelected");
02312                 return;
02313         }
02314 
02315         if (mCurrentParcelSelection->mWholeParcelSelected)
02316         {
02317                 gViewerWindow->alertXml("CannotJoinLandEntireParcelSelected");
02318                 return;
02319         }
02320 
02321         if (!mCurrentParcelSelection->mSelectedMultipleOwners)
02322         {
02323                 gViewerWindow->alertXml("CannotJoinLandSelection");
02324                 return;
02325         }
02326 
02327         gViewerWindow->alertXml("JoinLandWarning",
02328                 callbackJoinLand,
02329                 this);
02330 }
02331 
02332 // static
02333 void LLViewerParcelMgr::callbackJoinLand(S32 option, void* data)
02334 {
02335         LLViewerParcelMgr* self = (LLViewerParcelMgr*)data;
02336 
02337         LLVector3d parcel_center = (self->mWestSouth + self->mEastNorth) / 2.0;
02338         LLViewerRegion* region = gWorldp->getRegionFromPosGlobal(parcel_center);
02339         if (!region)
02340         {
02341                 gViewerWindow->alertXml("CannotJoinLandNoRegion");
02342                 return;
02343         }
02344 
02345         if (0 == option)
02346         {
02347                 LLVector3 west_south = region->getPosRegionFromGlobal(self->mWestSouth);
02348                 LLVector3 east_north = region->getPosRegionFromGlobal(self->mEastNorth);
02349 
02350                 LLMessageSystem* msg = gMessageSystem;
02351                 msg->newMessage("ParcelJoin");
02352                 msg->nextBlock("AgentData");
02353                 msg->addUUID("AgentID", gAgent.getID());
02354                 msg->addUUID("SessionID", gAgent.getSessionID());
02355                 msg->nextBlock("ParcelData");
02356                 msg->addF32("West", west_south.mV[VX]);
02357                 msg->addF32("South", west_south.mV[VY]);
02358                 msg->addF32("East", east_north.mV[VX]);
02359                 msg->addF32("North", east_north.mV[VY]);
02360                 msg->sendReliable(region->getHost());
02361         }
02362 }
02363 
02364 
02365 void LLViewerParcelMgr::startDeedLandToGroup()
02366 {
02367         if (!mSelected || !mCurrentParcel)
02368         {
02369                 gViewerWindow->alertXml("CannotDeedLandNothingSelected");
02370                 return;
02371         }
02372 
02373         if (mRequestResult == PARCEL_RESULT_NO_DATA)
02374         {
02375                 gViewerWindow->alertXml("CannotDeedLandWaitingForServer");
02376                 return;
02377         }
02378 
02379         if (mRequestResult == PARCEL_RESULT_MULTIPLE)
02380         {
02381                 gViewerWindow->alertXml("CannotDeedLandMultipleSelected");
02382                 return;
02383         }
02384 
02385         LLVector3d parcel_center = (mWestSouth + mEastNorth) / 2.0;
02386         LLViewerRegion* region = gWorldp->getRegionFromPosGlobal(parcel_center);
02387         if (!region)
02388         {
02389                 gViewerWindow->alertXml("CannotDeedLandNoRegion");
02390                 return;
02391         }
02392 
02393         /*
02394         if(!gAgent.isGodlike())
02395         {
02396                 if((region->getRegionFlags() & REGION_FLAGS_BLOCK_LAND_RESELL)
02397                         && (mCurrentParcel->getOwnerID() != region->getOwner()))
02398                 {
02399                         LLStringBase<char>::format_map_t args;
02400                         args["[REGION]"] = region->getName();
02401                         gViewerWindow->alertXml("CannotDeedLandNoTransfer", args);
02402                         return;
02403                 }
02404         }
02405         */
02406 
02407         deedLandToGroup();
02408 }
02409 void LLViewerParcelMgr::reclaimParcel()
02410 {
02411         LLParcel* parcel = gParcelMgr->getParcelSelection()->getParcel();
02412         LLViewerRegion* regionp = gParcelMgr->getSelectionRegion();
02413         if(parcel && parcel->getOwnerID().notNull()
02414            && (parcel->getOwnerID() != gAgent.getID())
02415            && regionp && (regionp->getOwner() == gAgent.getID()))
02416         {
02417                 LLMessageSystem* msg = gMessageSystem;
02418                 msg->newMessage("ParcelReclaim");
02419                 msg->nextBlock("AgentData");
02420                 msg->addUUID("AgentID", gAgent.getID());
02421                 msg->addUUID("SessionID", gAgent.getSessionID());
02422                 msg->nextBlock("Data");
02423                 msg->addS32("LocalID", parcel->getLocalID());
02424                 msg->sendReliable(regionp->getHost());
02425         }
02426 }
02427 
02428 // static
02429 void LLViewerParcelMgr::releaseAlertCB(S32 option, void *)
02430 {
02431         if (option == 0)
02432         {
02433                 // Send the release message, not a force
02434                 gParcelMgr->sendParcelRelease();
02435         }
02436 }
02437 
02438 void LLViewerParcelMgr::buyPass()
02439 {
02440         LLParcel* parcel = getParcelSelection()->getParcel();
02441         if (!parcel) return;
02442 
02443         LLViewerRegion* region = getSelectionRegion();
02444         if (!region) return;
02445 
02446         LLMessageSystem* msg = gMessageSystem;
02447         msg->newMessageFast(_PREHASH_ParcelBuyPass);
02448         msg->nextBlock("AgentData");
02449         msg->addUUID("AgentID", gAgent.getID());
02450         msg->addUUID("SessionID", gAgent.getSessionID());
02451         msg->nextBlockFast(_PREHASH_ParcelData);
02452         msg->addS32Fast(_PREHASH_LocalID, parcel->getLocalID() );
02453         msg->sendReliable( region->getHost() );
02454 }
02455 
02456 //Tells whether we are allowed to buy a pass or not
02457 BOOL LLViewerParcelMgr::isCollisionBanned()     
02458 { 
02459         if ((mCollisionBanned == BA_ALLOWED) || (mCollisionBanned == BA_NOT_ON_LIST) || (mCollisionBanned == BA_NOT_IN_GROUP))
02460                 return FALSE;
02461         else 
02462                 return TRUE;
02463 }
02464 
02465 // This implementation should mirror LLSimParcelMgr::isParcelOwnedBy
02466 // static
02467 BOOL LLViewerParcelMgr::isParcelOwnedByAgent(const LLParcel* parcelp, U64 group_proxy_power)
02468 {
02469         if (!parcelp)
02470         {
02471                 return FALSE;
02472         }
02473 
02474         // Gods can always assume ownership.
02475         if (gAgent.isGodlike())
02476         {
02477                 return TRUE;
02478         }
02479 
02480         // The owner of a parcel automatically gets all powersr.
02481         if (parcelp->getOwnerID() == gAgent.getID())
02482         {
02483                 return TRUE;
02484         }
02485 
02486         // Only gods can assume 'ownership' of public land.
02487         if (parcelp->isPublic())
02488         {
02489                 return FALSE;
02490         }
02491 
02492         // Return whether or not the agent has group_proxy_power powers in the
02493         // parcel's group.
02494         return gAgent.hasPowerInGroup(parcelp->getOwnerID(), group_proxy_power);
02495 }
02496 
02497 // This implementation should mirror llSimParcelMgr::isParcelModifiableBy
02498 // static
02499 BOOL LLViewerParcelMgr::isParcelModifiableByAgent(const LLParcel* parcelp, U64 group_proxy_power)
02500 {
02501         // If the agent can assume ownership, it is probably modifiable.
02502         BOOL rv = FALSE;
02503         if (parcelp)
02504         {
02505                 // *NOTE: This should only work for leased parcels, but group owned
02506                 // parcels cannot be OS_LEASED yet. Phoenix 2003-12-15.
02507                 rv = isParcelOwnedByAgent(parcelp, group_proxy_power);
02508 
02509                 // ... except for the case that the parcel is not OS_LEASED for agent-owned parcels.
02510                 if( (gAgent.getID() == parcelp->getOwnerID())
02511                         && !gAgent.isGodlike()
02512                         && (parcelp->getOwnershipStatus() != LLParcel::OS_LEASED) )
02513                 {
02514                         rv = FALSE;
02515                 }
02516         }
02517         return rv;
02518 }
02519 
02520 void sanitize_corners(const LLVector3d &corner1,
02521                                                                                 const LLVector3d &corner2,
02522                                                                                 LLVector3d &west_south_bottom,
02523                                                                                 LLVector3d &east_north_top)
02524 {
02525         west_south_bottom.mdV[VX] = llmin( corner1.mdV[VX], corner2.mdV[VX] );
02526         west_south_bottom.mdV[VY] = llmin( corner1.mdV[VY], corner2.mdV[VY] );
02527         west_south_bottom.mdV[VZ] = llmin( corner1.mdV[VZ], corner2.mdV[VZ] );
02528 
02529         east_north_top.mdV[VX] = llmax( corner1.mdV[VX], corner2.mdV[VX] );
02530         east_north_top.mdV[VY] = llmax( corner1.mdV[VY], corner2.mdV[VY] );
02531         east_north_top.mdV[VZ] = llmax( corner1.mdV[VZ], corner2.mdV[VZ] );
02532 }
02533 
02534 //
02535 // LLParcelSelection
02536 //
02537 LLParcelSelection::LLParcelSelection() : 
02538         mParcel(NULL),
02539         mSelectedMultipleOwners(FALSE),
02540         mWholeParcelSelected(FALSE),
02541         mSelectedSelfCount(0),
02542         mSelectedOtherCount(0),
02543         mSelectedPublicCount(0)
02544 {
02545 }
02546 
02547 LLParcelSelection::LLParcelSelection(LLParcel* parcel)  : 
02548         mParcel(parcel),
02549         mSelectedMultipleOwners(FALSE),
02550         mWholeParcelSelected(FALSE),
02551         mSelectedSelfCount(0),
02552         mSelectedOtherCount(0),
02553         mSelectedPublicCount(0)
02554 {
02555 }
02556 
02557 LLParcelSelection::~LLParcelSelection()
02558 {
02559 }
02560 
02561 BOOL LLParcelSelection::getMultipleOwners() const
02562 {
02563         return mSelectedMultipleOwners;
02564 }
02565 
02566 
02567 BOOL LLParcelSelection::getWholeParcelSelected() const
02568 {
02569         return mWholeParcelSelected;
02570 }
02571 
02572 
02573 S32 LLParcelSelection::getClaimableArea() const
02574 {
02575         const S32 UNIT_AREA = S32( PARCEL_GRID_STEP_METERS * PARCEL_GRID_STEP_METERS );
02576         return mSelectedPublicCount * UNIT_AREA;
02577 }
02578 
02579 bool LLParcelSelection::hasOthersSelected() const
02580 {
02581         return mSelectedOtherCount != 0;
02582 }
02583 
02584 static LLPointer<LLParcelSelection> sNullSelection;
02585 
02586 LLParcelSelection* get_null_parcel_selection()
02587 {
02588         if (sNullSelection.isNull())
02589         {
02590                 sNullSelection = new LLParcelSelection;
02591         }
02592         
02593         return sNullSelection;
02594 }
02595 
02596 void LLViewerParcelMgr::cleanupGlobals()
02597 {
02598         delete gParcelMgr;
02599         gParcelMgr = NULL;
02600         sNullSelection = NULL;
02601 }

Generated on Thu Jul 1 06:09:33 2010 for Second Life Viewer by  doxygen 1.4.7