lllandmark.cpp

Go to the documentation of this file.
00001 
00032 #include "linden_common.h"
00033 #include "lllandmark.h"
00034 
00035 #include <errno.h>
00036 
00037 #include "message.h"
00038 #include "llregionhandle.h"
00039 
00040 std::pair<LLUUID, U64> LLLandmark::mLocalRegion;
00041 LLLandmark::region_map_t LLLandmark::mRegions;
00042 LLLandmark::region_callback_t LLLandmark::mRegionCallback;
00043 
00044 LLLandmark::LLLandmark() :
00045         mGlobalPositionKnown(false)
00046 {
00047 }
00048 
00049 LLLandmark::LLLandmark(const LLVector3d& pos) :
00050         mGlobalPositionKnown(true),
00051         mGlobalPos( pos )
00052 {
00053 }
00054 
00055 bool LLLandmark::getGlobalPos(LLVector3d& pos)
00056 {
00057         if(mGlobalPositionKnown)
00058         {
00059                 pos = mGlobalPos;
00060         }
00061         else if(mRegionID.notNull())
00062         {
00063                 F32 g_x = -1.0;
00064                 F32 g_y = -1.0;
00065                 if(mRegionID == mLocalRegion.first)
00066                 {
00067                         from_region_handle(mLocalRegion.second, &g_x, &g_y);
00068                 }
00069                 else
00070                 {
00071                         region_map_t::iterator it = mRegions.find(mRegionID);
00072                         if(it != mRegions.end())
00073                         {
00074                                 from_region_handle((*it).second.mRegionHandle, &g_x, &g_y);
00075                         }
00076                 }
00077                 if((g_x > 0.f) && (g_y > 0.f))
00078                 {
00079                         pos.mdV[0] = g_x + mRegionPos.mV[0];
00080                         pos.mdV[1] = g_y + mRegionPos.mV[1];
00081                         pos.mdV[2] = mRegionPos.mV[2];
00082                         setGlobalPos(pos);
00083                 }
00084         }
00085         return mGlobalPositionKnown;
00086 }
00087 
00088 void LLLandmark::setGlobalPos(const LLVector3d& pos)
00089 {
00090         mGlobalPos = pos;
00091         mGlobalPositionKnown = true;
00092 }
00093 
00094 bool LLLandmark::getRegionID(LLUUID& region_id)
00095 {
00096         if(mRegionID.notNull())
00097         {
00098                 region_id = mRegionID;
00099                 return true;
00100         }
00101         return false;
00102 }
00103 
00104 LLVector3 LLLandmark::getRegionPos() const
00105 {
00106         return mRegionPos;
00107 }
00108 
00109 
00110 // static
00111 LLLandmark* LLLandmark::constructFromString(const char *buffer)
00112 {
00113         const char* cur = buffer;
00114         S32 chars_read = 0;
00115         S32 count = 0;
00116         U32 version = 0;
00117 
00118         // read version 
00119         count = sscanf( cur, "Landmark version %u\n%n", &version, &chars_read );
00120         if(count != 1)
00121         {
00122                 goto error;
00123         }
00124 
00125         if(version == 1)
00126         {
00127                 LLVector3d pos;
00128                 cur += chars_read;
00129                 // read position
00130                 count = sscanf( cur, "position %lf %lf %lf\n%n", pos.mdV+VX, pos.mdV+VY, pos.mdV+VZ, &chars_read );
00131                 if( count != 3 )
00132                 {
00133                         goto error;
00134                 }
00135                 cur += chars_read;
00136                 // llinfos << "Landmark read: " << pos << llendl;
00137                 
00138                 return new LLLandmark(pos);
00139         }
00140         else if(version == 2)
00141         {
00142                 // *NOTE: Changing the buffer size will require changing the
00143                 // scanf call below.
00144                 char region_id_str[MAX_STRING]; /* Flawfinder: ignore */
00145                 LLVector3 pos;
00146                 cur += chars_read;
00147                 count = sscanf( /* Flawfinder: ignore */
00148                         cur,
00149                         "region_id %254s\n%n",
00150                         region_id_str, &chars_read);
00151                 if(count != 1) goto error;
00152                 cur += chars_read;
00153                 count = sscanf(cur, "local_pos %f %f %f\n%n", pos.mV+VX, pos.mV+VY, pos.mV+VZ, &chars_read);
00154                 if(count != 3) goto error;
00155                 cur += chars_read;
00156                 LLLandmark* lm = new LLLandmark;
00157                 lm->mRegionID.set(region_id_str);
00158                 lm->mRegionPos = pos;
00159                 return lm;
00160         }
00161 
00162  error:
00163         llinfos << "Bad Landmark Asset: bad _DATA_ block." << llendl;
00164         return NULL;
00165 }
00166 
00167 
00168 // static
00169 void LLLandmark::registerCallbacks(LLMessageSystem* msg)
00170 {
00171         msg->setHandlerFunc("RegionIDAndHandleReply", &processRegionIDAndHandle);
00172 }
00173 
00174 // static
00175 void LLLandmark::requestRegionHandle(
00176         LLMessageSystem* msg,
00177         const LLHost& upstream_host,
00178         const LLUUID& region_id,
00179         LLRegionHandleCallback* callback)
00180 {
00181         if(region_id.isNull())
00182         {
00183                 // don't bother with checking - it's 0.
00184                 lldebugs << "requestRegionHandle: null" << llendl;
00185                 if(callback)
00186                 {
00187                         const U64 U64_ZERO = 0;
00188                         callback->dataReady(region_id, U64_ZERO);
00189                 }
00190         }
00191         else
00192         {
00193                 if(region_id == mLocalRegion.first)
00194                 {
00195                         lldebugs << "requestRegionHandle: local" << llendl;
00196                         if(callback)
00197                         {
00198                                 callback->dataReady(region_id, mLocalRegion.second);
00199                         }
00200                 }
00201                 else
00202                 {
00203                         region_map_t::iterator it = mRegions.find(region_id);
00204                         if(it == mRegions.end())
00205                         {
00206                                 lldebugs << "requestRegionHandle: upstream" << llendl;
00207                                 if(callback)
00208                                 {
00209                                         region_callback_t::value_type vt(region_id, callback);
00210                                         mRegionCallback.insert(vt);
00211                                 }
00212                                 lldebugs << "Landmark requesting information about: "
00213                                                  << region_id << llendl;
00214                                 msg->newMessage("RegionHandleRequest");
00215                                 msg->nextBlock("RequestBlock");
00216                                 msg->addUUID("RegionID", region_id);
00217                                 msg->sendReliable(upstream_host);
00218                         }
00219                         else if(callback)
00220                         {
00221                                 // we have the answer locally - just call the callack.
00222                                 lldebugs << "requestRegionHandle: ready" << llendl;
00223                                 callback->dataReady(region_id, (*it).second.mRegionHandle);
00224                         }
00225                 }
00226         }
00227 
00228         // As good a place as any to expire old entries.
00229         expireOldEntries();
00230 }
00231 
00232 // static
00233 void LLLandmark::setRegionHandle(const LLUUID& region_id, U64 region_handle)
00234 {
00235         mLocalRegion.first = region_id;
00236         mLocalRegion.second = region_handle;
00237 }
00238 
00239 
00240 // static
00241 void LLLandmark::processRegionIDAndHandle(LLMessageSystem* msg, void**)
00242 {
00243         LLUUID region_id;
00244         msg->getUUID("ReplyBlock", "RegionID", region_id);
00245         mRegions.erase(region_id);
00246         CacheInfo info;
00247         const F32 CACHE_EXPIRY_SECONDS = 60.0f * 10.0f; // ten minutes
00248         info.mTimer.setTimerExpirySec(CACHE_EXPIRY_SECONDS);
00249         msg->getU64("ReplyBlock", "RegionHandle", info.mRegionHandle);
00250         region_map_t::value_type vt(region_id, info);
00251         mRegions.insert(vt);
00252 
00253 #if LL_DEBUG
00254         U32 grid_x, grid_y;
00255         grid_from_region_handle(info.mRegionHandle, &grid_x, &grid_y);
00256         lldebugs << "Landmark got reply for region: " << region_id << " "
00257                          << grid_x << "," << grid_y << llendl;
00258 #endif
00259 
00260         // make all the callbacks here.
00261         region_callback_t::iterator it;
00262         while((it = mRegionCallback.find(region_id)) != mRegionCallback.end())
00263         {
00264                 (*it).second->dataReady(region_id, info.mRegionHandle);
00265                 mRegionCallback.erase(it);
00266         }
00267 }
00268 
00269 // static
00270 void LLLandmark::expireOldEntries()
00271 {
00272         for(region_map_t::iterator it = mRegions.begin(); it != mRegions.end(); )
00273         {
00274                 if((*it).second.mTimer.hasExpired())
00275                 {
00276                         mRegions.erase(it++);
00277                 }
00278                 else
00279                 {
00280                         ++it;
00281                 }
00282         }
00283 }

Generated on Thu Jul 1 06:08:48 2010 for Second Life Viewer by  doxygen 1.4.7