PageRenderTime 40ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llinventory/lllandmark.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 278 lines | 212 code | 26 blank | 40 comment | 37 complexity | 92b1bdfc2ffd369524d9aeec47382b1d MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file lllandmark.cpp
  3. * @brief Landmark asset class
  4. *
  5. * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "linden_common.h"
  27. #include "lllandmark.h"
  28. #include <errno.h>
  29. #include "message.h"
  30. #include "llregionhandle.h"
  31. std::pair<LLUUID, U64> LLLandmark::mLocalRegion;
  32. LLLandmark::region_map_t LLLandmark::mRegions;
  33. LLLandmark::region_callback_map_t LLLandmark::sRegionCallbackMap;
  34. LLLandmark::LLLandmark() :
  35. mGlobalPositionKnown(false)
  36. {
  37. }
  38. LLLandmark::LLLandmark(const LLVector3d& pos) :
  39. mGlobalPositionKnown(true),
  40. mGlobalPos( pos )
  41. {
  42. }
  43. bool LLLandmark::getGlobalPos(LLVector3d& pos)
  44. {
  45. if(mGlobalPositionKnown)
  46. {
  47. pos = mGlobalPos;
  48. }
  49. else if(mRegionID.notNull())
  50. {
  51. F32 g_x = -1.0;
  52. F32 g_y = -1.0;
  53. if(mRegionID == mLocalRegion.first)
  54. {
  55. from_region_handle(mLocalRegion.second, &g_x, &g_y);
  56. }
  57. else
  58. {
  59. region_map_t::iterator it = mRegions.find(mRegionID);
  60. if(it != mRegions.end())
  61. {
  62. from_region_handle((*it).second.mRegionHandle, &g_x, &g_y);
  63. }
  64. }
  65. if((g_x > 0.f) && (g_y > 0.f))
  66. {
  67. pos.mdV[0] = g_x + mRegionPos.mV[0];
  68. pos.mdV[1] = g_y + mRegionPos.mV[1];
  69. pos.mdV[2] = mRegionPos.mV[2];
  70. setGlobalPos(pos);
  71. }
  72. }
  73. return mGlobalPositionKnown;
  74. }
  75. void LLLandmark::setGlobalPos(const LLVector3d& pos)
  76. {
  77. mGlobalPos = pos;
  78. mGlobalPositionKnown = true;
  79. }
  80. bool LLLandmark::getRegionID(LLUUID& region_id)
  81. {
  82. if(mRegionID.notNull())
  83. {
  84. region_id = mRegionID;
  85. return true;
  86. }
  87. return false;
  88. }
  89. LLVector3 LLLandmark::getRegionPos() const
  90. {
  91. return mRegionPos;
  92. }
  93. // static
  94. LLLandmark* LLLandmark::constructFromString(const char *buffer)
  95. {
  96. const char* cur = buffer;
  97. S32 chars_read = 0;
  98. S32 count = 0;
  99. U32 version = 0;
  100. // read version
  101. count = sscanf( cur, "Landmark version %u\n%n", &version, &chars_read );
  102. if(count != 1)
  103. {
  104. goto error;
  105. }
  106. if(version == 1)
  107. {
  108. LLVector3d pos;
  109. cur += chars_read;
  110. // read position
  111. count = sscanf( cur, "position %lf %lf %lf\n%n", pos.mdV+VX, pos.mdV+VY, pos.mdV+VZ, &chars_read );
  112. if( count != 3 )
  113. {
  114. goto error;
  115. }
  116. cur += chars_read;
  117. // llinfos << "Landmark read: " << pos << llendl;
  118. return new LLLandmark(pos);
  119. }
  120. else if(version == 2)
  121. {
  122. // *NOTE: Changing the buffer size will require changing the
  123. // scanf call below.
  124. char region_id_str[MAX_STRING]; /* Flawfinder: ignore */
  125. LLVector3 pos;
  126. cur += chars_read;
  127. count = sscanf( /* Flawfinder: ignore */
  128. cur,
  129. "region_id %254s\n%n",
  130. region_id_str, &chars_read);
  131. if(count != 1) goto error;
  132. cur += chars_read;
  133. count = sscanf(cur, "local_pos %f %f %f\n%n", pos.mV+VX, pos.mV+VY, pos.mV+VZ, &chars_read);
  134. if(count != 3) goto error;
  135. cur += chars_read;
  136. LLLandmark* lm = new LLLandmark;
  137. lm->mRegionID.set(region_id_str);
  138. lm->mRegionPos = pos;
  139. return lm;
  140. }
  141. error:
  142. llinfos << "Bad Landmark Asset: bad _DATA_ block." << llendl;
  143. return NULL;
  144. }
  145. // static
  146. void LLLandmark::registerCallbacks(LLMessageSystem* msg)
  147. {
  148. msg->setHandlerFunc("RegionIDAndHandleReply", &processRegionIDAndHandle);
  149. }
  150. // static
  151. void LLLandmark::requestRegionHandle(
  152. LLMessageSystem* msg,
  153. const LLHost& upstream_host,
  154. const LLUUID& region_id,
  155. region_handle_callback_t callback)
  156. {
  157. if(region_id.isNull())
  158. {
  159. // don't bother with checking - it's 0.
  160. lldebugs << "requestRegionHandle: null" << llendl;
  161. if(callback)
  162. {
  163. const U64 U64_ZERO = 0;
  164. callback(region_id, U64_ZERO);
  165. }
  166. }
  167. else
  168. {
  169. if(region_id == mLocalRegion.first)
  170. {
  171. lldebugs << "requestRegionHandle: local" << llendl;
  172. if(callback)
  173. {
  174. callback(region_id, mLocalRegion.second);
  175. }
  176. }
  177. else
  178. {
  179. region_map_t::iterator it = mRegions.find(region_id);
  180. if(it == mRegions.end())
  181. {
  182. lldebugs << "requestRegionHandle: upstream" << llendl;
  183. if(callback)
  184. {
  185. region_callback_map_t::value_type vt(region_id, callback);
  186. sRegionCallbackMap.insert(vt);
  187. }
  188. lldebugs << "Landmark requesting information about: "
  189. << region_id << llendl;
  190. msg->newMessage("RegionHandleRequest");
  191. msg->nextBlock("RequestBlock");
  192. msg->addUUID("RegionID", region_id);
  193. msg->sendReliable(upstream_host);
  194. }
  195. else if(callback)
  196. {
  197. // we have the answer locally - just call the callack.
  198. lldebugs << "requestRegionHandle: ready" << llendl;
  199. callback(region_id, (*it).second.mRegionHandle);
  200. }
  201. }
  202. }
  203. // As good a place as any to expire old entries.
  204. expireOldEntries();
  205. }
  206. // static
  207. void LLLandmark::setRegionHandle(const LLUUID& region_id, U64 region_handle)
  208. {
  209. mLocalRegion.first = region_id;
  210. mLocalRegion.second = region_handle;
  211. }
  212. // static
  213. void LLLandmark::processRegionIDAndHandle(LLMessageSystem* msg, void**)
  214. {
  215. LLUUID region_id;
  216. msg->getUUID("ReplyBlock", "RegionID", region_id);
  217. mRegions.erase(region_id);
  218. CacheInfo info;
  219. const F32 CACHE_EXPIRY_SECONDS = 60.0f * 10.0f; // ten minutes
  220. info.mTimer.setTimerExpirySec(CACHE_EXPIRY_SECONDS);
  221. msg->getU64("ReplyBlock", "RegionHandle", info.mRegionHandle);
  222. region_map_t::value_type vt(region_id, info);
  223. mRegions.insert(vt);
  224. #if LL_DEBUG
  225. U32 grid_x, grid_y;
  226. grid_from_region_handle(info.mRegionHandle, &grid_x, &grid_y);
  227. lldebugs << "Landmark got reply for region: " << region_id << " "
  228. << grid_x << "," << grid_y << llendl;
  229. #endif
  230. // make all the callbacks here.
  231. region_callback_map_t::iterator it;
  232. while((it = sRegionCallbackMap.find(region_id)) != sRegionCallbackMap.end())
  233. {
  234. (*it).second(region_id, info.mRegionHandle);
  235. sRegionCallbackMap.erase(it);
  236. }
  237. }
  238. // static
  239. void LLLandmark::expireOldEntries()
  240. {
  241. for(region_map_t::iterator it = mRegions.begin(); it != mRegions.end(); )
  242. {
  243. if((*it).second.mTimer.hasExpired())
  244. {
  245. mRegions.erase(it++);
  246. }
  247. else
  248. {
  249. ++it;
  250. }
  251. }
  252. }