llworldmap.cpp 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302
  1. /**
  2. * @file llworldmap.cpp
  3. * @brief Underlying data representation for map of the world
  4. *
  5. * $LicenseInfo:firstyear=2003&license=viewergpl$
  6. *
  7. * Copyright (c) 2003-2009, Linden Research, Inc.
  8. * Copyright (c) 2009-2021, Henri Beauchamp.
  9. * Changes by Henri Beauchamp:
  10. * - Cleaned up/reorganized the code (which was spread over three classes).
  11. * - Backported web map tiles support from v2/3 viewers while keeping the old
  12. * terrain-only map support.
  13. * - Adapted the code for OpenSim variable region size support.
  14. * - Allowed to keep both objects and terrain map tiles in memory (avoids
  15. * seeing the map tiles fully reloaded at each world map tab change).
  16. *
  17. * Second Life Viewer Source Code
  18. * The source code in this file ("Source Code") is provided by Linden Lab
  19. * to you under the terms of the GNU General Public License, version 2.0
  20. * ("GPL"), unless you have obtained a separate licensing agreement
  21. * ("Other License"), formally executed by you and Linden Lab. Terms of
  22. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  23. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  24. *
  25. * There are special exceptions to the terms and conditions of the GPL as
  26. * it is applied to this Source Code. View the full text of the exception
  27. * in the file doc/FLOSS-exception.txt in this software distribution, or
  28. * online at
  29. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  30. *
  31. * By copying, modifying or distributing this software, you acknowledge
  32. * that you have read and understood your obligations described above,
  33. * and agree to abide by those obligations.
  34. *
  35. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  36. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  37. * COMPLETENESS OR PERFORMANCE.
  38. * $/LicenseInfo$
  39. */
  40. #include "llviewerprecompiledheaders.h"
  41. #include "llworldmap.h"
  42. #include "llregionflags.h"
  43. #include "llregionhandle.h"
  44. #include "llmessage.h"
  45. #include "llagent.h"
  46. #include "llfloaterworldmap.h"
  47. #include "llgridmanager.h"
  48. #include "lltracker.h"
  49. #include "llviewercontrol.h"
  50. #include "llviewertexturelist.h"
  51. #include "llworld.h"
  52. LLWorldMap gWorldMap;
  53. bool LLWorldMap::sGotMapURL = false;
  54. bool LLWorldMap::sMapURLSetOnLogin = false;
  55. std::string LLWorldMap::sMapURL;
  56. constexpr F32 REQUEST_ITEMS_TIMER = 600.f; // 10 minutes
  57. //-----------------------------------------------------------------------------
  58. // LLItemInfo class
  59. //-----------------------------------------------------------------------------
  60. LLItemInfo::LLItemInfo(F32 global_x, F32 global_y, const std::string& name,
  61. const LLUUID& id, S32 extra, S32 extra2)
  62. : mName(name),
  63. mPosGlobal(global_x, global_y, 40.0),
  64. mID(id),
  65. mSelected(false),
  66. mExtra(extra),
  67. mExtra2(extra2)
  68. {
  69. mRegionHandle = to_region_handle(mPosGlobal);
  70. }
  71. LLSimInfo::LLSimInfo()
  72. : mHandle(0),
  73. mAgentsUpdateTime(0.0),
  74. mAgentsCount(-1),
  75. mShowAgentLocations(false),
  76. mAccess(0x0),
  77. mRegionFlags(0x0),
  78. mAlpha(-1.f),
  79. // Variable region size support
  80. mSizeX(REGION_WIDTH_METERS),
  81. mSizeY(REGION_WIDTH_METERS)
  82. {
  83. }
  84. LLVector3d LLSimInfo::getGlobalOrigin() const
  85. {
  86. return from_region_handle(mHandle);
  87. }
  88. LLVector3d LLSimInfo::getGlobalPos(LLVector3 local_pos) const
  89. {
  90. LLVector3d pos = from_region_handle(mHandle);
  91. pos.mdV[VX] += local_pos.mV[VX];
  92. pos.mdV[VY] += local_pos.mV[VY];
  93. pos.mdV[VZ] += local_pos.mV[VZ];
  94. return pos;
  95. }
  96. //-----------------------------------------------------------------------------
  97. // LLWorldMap class
  98. //-----------------------------------------------------------------------------
  99. LLWorldMap::LLWorldMap()
  100. : mIsTrackingUnknownLocation(false),
  101. mInvalidLocation(false),
  102. mIsTrackingDoubleClick(false),
  103. mIsTrackingCommit(false),
  104. mUnknownLocation(0, 0, 0),
  105. mRequestLandForSale(true),
  106. mCurrentMap(0),
  107. mMinX(U32_MAX),
  108. mMaxX(U32_MIN),
  109. mMinY(U32_MAX),
  110. mMaxY(U32_MIN),
  111. mSLURLRegionName(),
  112. mSLURLRegionHandle(0),
  113. mSLURL(),
  114. mSLURLCallback(NULL),
  115. mSLURLTeleport(false)
  116. {
  117. clearSimFlags();
  118. for (S32 map = 0; map < MAP_SIM_IMAGE_TYPES; ++map)
  119. {
  120. mMapLoaded[map] = false;
  121. }
  122. }
  123. LLWorldMap::~LLWorldMap()
  124. {
  125. reset();
  126. mAgentLocationsMap.clear();
  127. }
  128. void LLWorldMap::reset()
  129. {
  130. for (sim_info_map_t::iterator it = mSimInfoMap.begin(),
  131. end = mSimInfoMap.end();
  132. it != end; ++it)
  133. {
  134. delete it->second;
  135. }
  136. mSimInfoMap.clear();
  137. eraseItems(true);
  138. for (S32 i = 0; i < MAP_SIM_IMAGE_TYPES; ++i)
  139. {
  140. mMapLoaded[i] = false;
  141. mMapLayers[i].clear();
  142. mMapBlockMap[i].clear();
  143. }
  144. mMinX = U32_MAX;
  145. mMaxX = U32_MIN;
  146. mMinY = U32_MAX;
  147. mMaxY = U32_MIN;
  148. }
  149. void LLWorldMap::eraseItems(bool force)
  150. {
  151. if (force || mRequestTimer.getElapsedTimeF32() > REQUEST_ITEMS_TIMER)
  152. {
  153. mRequestTimer.reset();
  154. mTelehubs.clear();
  155. mInfohubs.clear();
  156. mPGEvents.clear();
  157. mMatureEvents.clear();
  158. mAdultEvents.clear();
  159. mLandForSale.clear();
  160. }
  161. #if 0 // Persistent data
  162. mAgentLocationsMap.clear();
  163. #endif
  164. }
  165. void LLWorldMap::clearImageRefs(S32 layer)
  166. {
  167. for (sim_info_map_t::iterator it = mSimInfoMap.begin(),
  168. end = mSimInfoMap.end();
  169. it != end; ++it)
  170. {
  171. LLSimInfo* info = it->second;
  172. if ((layer <= 0 || layer > 1) && info->mCurrentImage[0])
  173. {
  174. info->mCurrentImage[0]->setBoostLevel(0);
  175. info->mCurrentImage[0] = NULL;
  176. }
  177. if ((layer == 1 || layer < 0) && info->mCurrentImage[1])
  178. {
  179. info->mCurrentImage[1]->setBoostLevel(0);
  180. info->mCurrentImage[1] = NULL;
  181. }
  182. if (info->mOverlayImage)
  183. {
  184. info->mOverlayImage->setBoostLevel(0);
  185. info->mOverlayImage = NULL;
  186. }
  187. }
  188. }
  189. // Does not clear the already-loaded sim infos, just re-requests them
  190. void LLWorldMap::clearSimFlags()
  191. {
  192. for (S32 map = 0; map < MAP_SIM_IMAGE_TYPES; ++map)
  193. {
  194. mMapBlockMap[map].clear();
  195. }
  196. }
  197. LLSimInfo* LLWorldMap::simInfoFromPosGlobal(const LLVector3d& pos_global)
  198. {
  199. return simInfoFromHandle(to_region_handle(pos_global));
  200. }
  201. LLSimInfo* LLWorldMap::simInfoFromHandle(U64 handle)
  202. {
  203. sim_info_map_t::iterator it = mSimInfoMap.find(handle);
  204. sim_info_map_t::iterator end = mSimInfoMap.end();
  205. if (it != end)
  206. {
  207. LLSimInfo* sim_info = it->second;
  208. if (sim_info)
  209. {
  210. return sim_info;
  211. }
  212. }
  213. // Variable region size support
  214. U32 x = 0;
  215. U32 y = 0;
  216. from_region_handle(handle, &x, &y);
  217. for (it = mSimInfoMap.begin(); it != end; ++it)
  218. {
  219. U32 tx, ty;
  220. from_region_handle(it->first, &tx, &ty);
  221. LLSimInfo* info = it->second;
  222. if (info && x >= tx && x < tx + info->getSizeX() &&
  223. y >= ty && y < ty + info->getSizeY())
  224. {
  225. return info;
  226. }
  227. }
  228. return NULL;
  229. }
  230. LLSimInfo* LLWorldMap::simInfoFromName(std::string sim_name)
  231. {
  232. if (sim_name.empty())
  233. {
  234. return NULL;
  235. }
  236. LLStringUtil::toUpper(sim_name);
  237. std::string sim_name2;
  238. for (sim_info_map_t::iterator it = mSimInfoMap.begin(),
  239. end = mSimInfoMap.end();
  240. it != end; ++it)
  241. {
  242. LLSimInfo* sim_info = it->second;
  243. if (!sim_info) continue;
  244. sim_name2 = sim_info->mName;
  245. LLStringUtil::toUpper(sim_name2);
  246. if (LLStringOps::collate(sim_name.c_str(), sim_name2.c_str()) == 0)
  247. {
  248. return sim_info;
  249. }
  250. }
  251. return NULL;
  252. }
  253. bool LLWorldMap::simNameFromPosGlobal(const LLVector3d& pos_global,
  254. std::string& sim_name)
  255. {
  256. U64 handle = to_region_handle(pos_global);
  257. sim_info_map_t::iterator it = mSimInfoMap.find(handle);
  258. if (it != mSimInfoMap.end())
  259. {
  260. LLSimInfo* info = it->second;
  261. sim_name = info->mName;
  262. return true;
  263. }
  264. sim_name = "(unknown region)";
  265. return false;
  266. }
  267. void LLWorldMap::setCurrentLayer(U32 layer, bool request_layer)
  268. {
  269. if (layer > MAP_SIM_TERRAIN)
  270. {
  271. llwarns << "Bad layer number: " << layer << llendl;
  272. return;
  273. }
  274. if (mCurrentMap != layer)
  275. {
  276. mCurrentMap = layer;
  277. #if 0 // Keep already loaded tiles ! HB
  278. clearImageRefs(layer);
  279. #endif
  280. clearSimFlags();
  281. }
  282. if (!mMapLoaded[layer] || request_layer)
  283. {
  284. sendMapLayerRequest();
  285. }
  286. if (mTelehubs.empty() || mInfohubs.empty())
  287. {
  288. // Request for telehubs
  289. sendItemRequest(MAP_ITEM_TELEHUB);
  290. }
  291. if (mPGEvents.empty())
  292. {
  293. // Request for events
  294. sendItemRequest(MAP_ITEM_PG_EVENT);
  295. }
  296. if (mMatureEvents.empty())
  297. {
  298. // Request for events (mature)
  299. sendItemRequest(MAP_ITEM_MATURE_EVENT);
  300. }
  301. if (mAdultEvents.empty())
  302. {
  303. // Request for events (adult)
  304. sendItemRequest(MAP_ITEM_ADULT_EVENT);
  305. }
  306. if (mLandForSale.empty())
  307. {
  308. // Request for Land For Sale
  309. sendItemRequest(MAP_ITEM_LAND_FOR_SALE);
  310. }
  311. if (mLandForSaleAdult.empty())
  312. {
  313. // Request for Land For Sale
  314. sendItemRequest(MAP_ITEM_LAND_FOR_SALE_ADULT);
  315. }
  316. }
  317. void LLWorldMap::forceUpdateRegion(U64 handle)
  318. {
  319. sim_info_map_t::iterator it = mSimInfoMap.find(handle);
  320. if (it != mSimInfoMap.end())
  321. {
  322. LLSimInfo* info = it->second;
  323. if (info->mCurrentImage[mCurrentMap])
  324. {
  325. info->mCurrentImage[mCurrentMap]->setBoostLevel(0);
  326. info->mCurrentImage[mCurrentMap] = NULL;
  327. }
  328. if (info->mOverlayImage)
  329. {
  330. info->mOverlayImage->setBoostLevel(0);
  331. info->mOverlayImage = NULL;
  332. }
  333. delete info;
  334. mSimInfoMap.erase(it);
  335. }
  336. U32 x, y;
  337. grid_from_region_handle(handle, &x, &y);
  338. updateRegions(x, y, x, y, true);
  339. }
  340. // Loads all regions in a given rectangle (in region grid coordinates, i.e.
  341. // world / 256 meters). Returns the number of requested map blocks.
  342. U32 LLWorldMap::updateRegions(S32 x0, S32 y0, S32 x1, S32 y1, bool force_upd)
  343. {
  344. U32 blocks_requested = 0;
  345. // Convert those boundaries to the corresponding (MAP_BLOCK_SIZE x
  346. // MAP_BLOCK_SIZE) block coordinates
  347. U32 global_x0 = x0 / MAP_BLOCK_SIZE;
  348. U32 global_x1 = x1 / MAP_BLOCK_SIZE;
  349. U32 global_y0 = y0 / MAP_BLOCK_SIZE;
  350. U32 global_y1 = y1 / MAP_BLOCK_SIZE;
  351. // There is a bunch of extra logic here, as OpenSim grids support sim
  352. // coordinates that extend beyond the range used on the SL grid. We
  353. // basically just extend what LL had here by nesting the mMapBlockLoaded
  354. // array in a 'dynamic' grid, essentially making that array a 'block'
  355. // itself.
  356. // MapBlockRequest uses U16 for coordinate components. In order not to
  357. // exceed U16_MAX values, MAP_BLOCK_RES*MAP_BLOCK_SIZE*(i or j) cannot
  358. // exceed U16_MAX(65535)
  359. U32 max_range = (U16_MAX + 1) / MAP_BLOCK_RES/MAP_BLOCK_SIZE - 1;
  360. // Desired coordinate ranges in our 'dynamic' grid of 512x512 grids of 4x4
  361. // sim blocks.
  362. U32 map_block_x0 = global_x0 / MAP_BLOCK_RES;
  363. U32 map_block_x1 = llmin(global_x1 / MAP_BLOCK_RES, max_range);
  364. U32 map_block_y0 = global_y0 / MAP_BLOCK_RES;
  365. U32 map_block_y1 = llmin(global_y1 / MAP_BLOCK_RES, max_range);
  366. for (U32 i = map_block_x0; i <= map_block_x1; ++i)
  367. {
  368. for (U32 j = map_block_y0; j <= map_block_y1; ++j)
  369. {
  370. // Desired coordinate ranges in our 512x512 grids of 4x4 sim
  371. // blocks.
  372. x0 = global_x0 - i * MAP_BLOCK_RES;
  373. x1 = llmin(global_x1 - i * (U32)MAP_BLOCK_RES,
  374. (U32)MAP_BLOCK_RES - 1);
  375. y0 = global_y0 - j * MAP_BLOCK_RES;
  376. y1 = llmin(global_y1 - j * (U32)MAP_BLOCK_RES,
  377. (U32)MAP_BLOCK_RES - 1);
  378. std::vector<bool>& block = mMapBlockMap[mCurrentMap][(i << 16) | j];
  379. if (force_upd)
  380. {
  381. block.clear();
  382. }
  383. if (block.empty())
  384. {
  385. // New block. Allocate the array and set all entries to false
  386. // (seen as mMapBlockLoaded in v3)
  387. block.resize(MAP_BLOCK_RES * MAP_BLOCK_RES, false);
  388. }
  389. // Load the region info those blocks
  390. for (S32 block_x = llmax(x0, 0),
  391. count_x = llmin(x1, MAP_BLOCK_RES - 1);
  392. block_x <= count_x; ++block_x)
  393. {
  394. for (S32 block_y = llmax(y0, 0),
  395. count_y = llmin(y1, MAP_BLOCK_RES - 1);
  396. block_y <= count_y; ++block_y)
  397. {
  398. S32 offset = block_x | (block_y * MAP_BLOCK_RES);
  399. if (!block[offset])
  400. {
  401. U16 min_x = (block_x + i * MAP_BLOCK_RES) *
  402. MAP_BLOCK_SIZE;
  403. U16 max_x = min_x + MAP_BLOCK_SIZE - 1;
  404. U16 min_y = (block_y + j * MAP_BLOCK_RES) *
  405. MAP_BLOCK_SIZE;
  406. U16 max_y = min_y + MAP_BLOCK_SIZE - 1;
  407. sendMapBlockRequest(min_x, min_y, max_x, max_y);
  408. block[offset] = true;
  409. ++blocks_requested;
  410. }
  411. }
  412. }
  413. }
  414. }
  415. return blocks_requested;
  416. }
  417. void LLWorldMap::sendItemRequest(U32 type, U64 handle)
  418. {
  419. LLMessageSystem* msg = gMessageSystemp;
  420. msg->newMessageFast(_PREHASH_MapItemRequest);
  421. msg->nextBlockFast(_PREHASH_AgentData);
  422. msg->addUUIDFast(_PREHASH_AgentID, gAgentID);
  423. msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
  424. msg->addU32Fast(_PREHASH_Flags, mCurrentMap);
  425. msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
  426. msg->addBoolFast(_PREHASH_Godlike, false); // Filled in on sim
  427. msg->nextBlockFast(_PREHASH_RequestData);
  428. msg->addU32Fast(_PREHASH_ItemType, type);
  429. msg->addU64Fast(_PREHASH_RegionHandle, handle); // Filled in on sim if zero
  430. gAgent.sendReliableMessage();
  431. }
  432. bool LLWorldMap::isTrackedUnknownLocation(U32 x, U32 y) const
  433. {
  434. return mIsTrackingUnknownLocation && mUnknownLocation.mdV[0] >= x &&
  435. mUnknownLocation.mdV[0] < x + 256 && mUnknownLocation.mdV[1] >= y &&
  436. mUnknownLocation.mdV[1] < y + 256;
  437. }
  438. //static
  439. void LLWorldMap::mapLayerRequestCallback(LLSD result)
  440. {
  441. if (!gFloaterWorldMapp) return;
  442. llinfos << "Got result from capability" << llendl;
  443. result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
  444. S32 agent_flags = result["AgentData"]["Flags"];
  445. if (agent_flags < 0 || agent_flags >= MAP_SIM_IMAGE_TYPES)
  446. {
  447. llwarns << "Invalid map image layer returned: " << agent_flags
  448. << llendl;
  449. return;
  450. }
  451. LLTexUnit* unit0 = gGL.getTexUnit(0);
  452. LLUUID image_id;
  453. gWorldMap.mMapLayers[agent_flags].clear();
  454. bool use_web_map_tiles = useWebMapTiles();
  455. bool adjust = false;
  456. for (LLSD::array_const_iterator iter = result["LayerData"].beginArray(),
  457. end = result["LayerData"].endArray();
  458. iter != end; ++iter)
  459. {
  460. const LLSD& layer_data = *iter;
  461. LLWorldMapLayer new_layer;
  462. new_layer.mLayerDefined = true;
  463. new_layer.mLayerExtents.mLeft = layer_data["Left"];
  464. new_layer.mLayerExtents.mRight = layer_data["Right"];
  465. new_layer.mLayerExtents.mBottom = layer_data["Bottom"];
  466. new_layer.mLayerExtents.mTop = layer_data["Top"];
  467. new_layer.mLayerImageID = layer_data["ImageID"];
  468. #if 0 // No good... Maybe using of level 2 and higher web maps ?
  469. if (use_web_map_tiles)
  470. {
  471. new_layer.mLayerImage =
  472. LLWorldMap::loadObjectsTile((U32)new_layer.mLayerExtents.mLeft,
  473. (U32)new_layer.mLayerExtents.mBottom);
  474. }
  475. else
  476. #endif
  477. new_layer.mLayerImage =
  478. LLViewerTextureManager::getFetchedTexture(new_layer.mLayerImageID);
  479. unit0->bind(new_layer.mLayerImage.get());
  480. new_layer.mLayerImage->setAddressMode(LLTexUnit::TAM_CLAMP);
  481. F32 x_meters = F32(new_layer.mLayerExtents.mLeft * REGION_WIDTH_UNITS);
  482. F32 y_meters = F32(new_layer.mLayerExtents.mBottom *
  483. REGION_WIDTH_UNITS);
  484. if (gWorldMap.extendAABB((U32)x_meters, (U32)y_meters,
  485. U32(x_meters + REGION_WIDTH_UNITS *
  486. new_layer.mLayerExtents.getWidth()),
  487. U32(y_meters + REGION_WIDTH_UNITS *
  488. new_layer.mLayerExtents.getHeight())))
  489. {
  490. adjust = true;
  491. }
  492. gWorldMap.mMapLayers[agent_flags].push_back(new_layer);
  493. }
  494. gWorldMap.mMapLoaded[agent_flags] = true;
  495. if (adjust)
  496. {
  497. gFloaterWorldMapp->adjustZoomSliderBounds();
  498. }
  499. bool found_null_sim = false;
  500. adjust = false;
  501. if (result.has("MapBlocks"))
  502. {
  503. U32 cur_layer = gWorldMap.mCurrentMap;
  504. sim_info_map_t::iterator sit;
  505. const LLSD& map_blocks = result["MapBlocks"];
  506. for (LLSD::array_const_iterator iter = map_blocks.beginArray(),
  507. end = map_blocks.endArray();
  508. iter != end; ++iter)
  509. {
  510. const LLSD& map_block = *iter;
  511. S32 x_regions = map_block["X"].asInteger();
  512. S32 y_regions = map_block["Y"].asInteger();
  513. std::string name = map_block["Name"].asString();
  514. S32 access = map_block["Access"].asInteger();
  515. U64 region_flags = map_block["RegionFlags"].asInteger();
  516. LLUUID image_id = map_block["MapImageID"].asUUID();
  517. U32 x_meters = x_regions * REGION_WIDTH_UNITS;
  518. U32 y_meters = y_regions * REGION_WIDTH_UNITS;
  519. if (access == 255)
  520. {
  521. // This region does not exist
  522. if (gWorldMap.isTrackedUnknownLocation(x_meters, y_meters))
  523. {
  524. // We were tracking this location, but it does not exist
  525. gWorldMap.mInvalidLocation = true;
  526. }
  527. found_null_sim = true;
  528. continue;
  529. }
  530. if (gWorldMap.extendAABB(x_meters, y_meters,
  531. x_meters + REGION_WIDTH_UNITS,
  532. y_meters + REGION_WIDTH_UNITS))
  533. {
  534. adjust = true;
  535. }
  536. U64 handle = to_region_handle(x_meters, y_meters);
  537. LLSimInfo* siminfo = new LLSimInfo();
  538. sit = gWorldMap.mSimInfoMap.find(handle);
  539. if (sit != gWorldMap.mSimInfoMap.end())
  540. {
  541. LLSimInfo* oldinfo = sit->second;
  542. siminfo->mAgentsUpdateTime = oldinfo->mAgentsUpdateTime;
  543. for (S32 image = 0; image < MAP_SIM_IMAGE_TYPES; ++image)
  544. {
  545. siminfo->mMapImageID[image] = oldinfo->mMapImageID[image];
  546. }
  547. delete oldinfo;
  548. }
  549. gWorldMap.mSimInfoMap[handle] = siminfo;
  550. siminfo->mHandle = handle;
  551. siminfo->mName.assign(name);
  552. siminfo->mAccess = access;
  553. siminfo->mRegionFlags = region_flags;
  554. siminfo->mMapImageID[agent_flags] = image_id;
  555. if (use_web_map_tiles)
  556. {
  557. siminfo->mCurrentImage[cur_layer] =
  558. loadObjectsTile((U32)x_regions, (U32)y_regions);
  559. }
  560. else
  561. {
  562. siminfo->mCurrentImage[cur_layer] =
  563. LLViewerTextureManager::getFetchedTexture(siminfo->mMapImageID[agent_flags]);
  564. }
  565. siminfo->mCurrentImage[cur_layer]->setAddressMode(LLTexUnit::TAM_CLAMP);
  566. unit0->bind(siminfo->mCurrentImage[cur_layer].get());
  567. if (siminfo->mMapImageID[2].notNull())
  568. {
  569. siminfo->mOverlayImage =
  570. LLViewerTextureManager::getFetchedTexture(siminfo->mMapImageID[2]);
  571. }
  572. else
  573. {
  574. siminfo->mOverlayImage = NULL;
  575. }
  576. if (gWorldMap.isTrackedUnknownLocation(x_meters, y_meters))
  577. {
  578. if (siminfo->mAccess == SIM_ACCESS_DOWN)
  579. {
  580. // We were tracking this location, but it does not exist
  581. gWorldMap.mInvalidLocation = true;
  582. }
  583. else
  584. {
  585. // We were tracking this location, and it does exist
  586. gFloaterWorldMapp->trackLocation(gWorldMap.mUnknownLocation);
  587. // Try another TP method...
  588. if (gWorldMap.mIsTrackingDoubleClick)
  589. {
  590. LLVector3d pos_global =
  591. gTracker.getTrackedPositionGlobal();
  592. gAgent.teleportViaLocation(pos_global);
  593. }
  594. }
  595. }
  596. }
  597. }
  598. if (adjust)
  599. {
  600. gFloaterWorldMapp->adjustZoomSliderBounds();
  601. }
  602. gFloaterWorldMapp->updateSims(found_null_sim);
  603. }
  604. void LLWorldMap::sendMapLayerRequest()
  605. {
  606. LLSD body;
  607. body["Flags"] = (S32)mCurrentMap;
  608. LLAgent::httpCallback_t succ =
  609. boost::bind(&LLWorldMap::mapLayerRequestCallback, _1);
  610. const char* cap_name = gAgent.isGodlike() ? "MapLayerGod" : "MapLayer";
  611. if (gAgent.requestPostCapability(cap_name, body, succ))
  612. {
  613. llinfos << "Sent map layer request via capability: " << cap_name
  614. << llendl;
  615. }
  616. else
  617. {
  618. llinfos << "Sending map layer request via message system" << llendl;
  619. LLMessageSystem* msg = gMessageSystemp;
  620. // Request for layer
  621. msg->newMessageFast(_PREHASH_MapLayerRequest);
  622. msg->nextBlockFast(_PREHASH_AgentData);
  623. msg->addUUIDFast(_PREHASH_AgentID, gAgentID);
  624. msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
  625. msg->addU32Fast(_PREHASH_Flags, mCurrentMap);
  626. msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
  627. msg->addBoolFast(_PREHASH_Godlike, false); // Filled in on sim
  628. gAgent.sendReliableMessage();
  629. if (mRequestLandForSale)
  630. {
  631. msg->newMessageFast(_PREHASH_MapLayerRequest);
  632. msg->nextBlockFast(_PREHASH_AgentData);
  633. msg->addUUIDFast(_PREHASH_AgentID, gAgentID);
  634. msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
  635. msg->addU32Fast(_PREHASH_Flags, 2);
  636. msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
  637. msg->addBoolFast(_PREHASH_Godlike, false); // Filled in on sim
  638. gAgent.sendReliableMessage();
  639. }
  640. }
  641. }
  642. void LLWorldMap::sendNamedRegionRequest(const std::string& region_name)
  643. {
  644. // Request for region data
  645. LLMessageSystem* msg = gMessageSystemp;
  646. msg->newMessageFast(_PREHASH_MapNameRequest);
  647. msg->nextBlockFast(_PREHASH_AgentData);
  648. msg->addUUIDFast(_PREHASH_AgentID, gAgentID);
  649. msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
  650. #if 0
  651. msg->addU32Fast(_PREHASH_Flags, mCurrentMap);
  652. #else
  653. // Note: in OpenSIM, send request with layer = 2, which is what v2+ viewers
  654. // (i.e. viewers without terrain-only layer support) always do... Doing
  655. // otherwise confuses the newest OpenSIM servers. :-( HB
  656. // *TODO: verify this is still needed. HB
  657. msg->addU32Fast(_PREHASH_Flags,
  658. gIsInSecondLife ? mCurrentMap : MAP_SIM_LAND_FOR_SALE);
  659. #endif
  660. msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
  661. msg->addBoolFast(_PREHASH_Godlike, false); // Filled in on sim
  662. msg->nextBlockFast(_PREHASH_NameData);
  663. msg->addStringFast(_PREHASH_Name, region_name);
  664. gAgent.sendReliableMessage();
  665. }
  666. void LLWorldMap::sendNamedRegionRequest(const std::string& region_name,
  667. url_callback_t callback,
  668. const std::string& callback_url,
  669. // Teleport when result returned
  670. bool teleport)
  671. {
  672. mSLURLRegionName = region_name;
  673. mSLURLRegionHandle = 0;
  674. mSLURL = callback_url;
  675. mSLURLCallback = callback;
  676. mSLURLTeleport = teleport;
  677. sendNamedRegionRequest(mSLURLRegionName);
  678. }
  679. void LLWorldMap::sendHandleRegionRequest(U64 region_handle,
  680. url_callback_t callback,
  681. const std::string& url, bool teleport)
  682. {
  683. mSLURLRegionName.clear();
  684. mSLURLRegionHandle = region_handle;
  685. mSLURL = url;
  686. mSLURLCallback = callback;
  687. mSLURLTeleport = teleport;
  688. U32 global_x, global_y;
  689. from_region_handle(region_handle, &global_x, &global_y);
  690. U16 grid_x = (U16)(global_x / REGION_WIDTH_UNITS);
  691. U16 grid_y = (U16)(global_y / REGION_WIDTH_UNITS);
  692. sendMapBlockRequest(grid_x, grid_y, grid_x, grid_y, true);
  693. }
  694. void LLWorldMap::sendMapBlockRequest(U16 min_x, U16 min_y, U16 max_x,
  695. U16 max_y, bool return_nonexistent)
  696. {
  697. LLMessageSystem* msg = gMessageSystemp;
  698. msg->newMessageFast(_PREHASH_MapBlockRequest);
  699. msg->nextBlockFast(_PREHASH_AgentData);
  700. msg->addUUIDFast(_PREHASH_AgentID, gAgentID);
  701. msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
  702. U32 flags = mCurrentMap;
  703. flags |= (return_nonexistent ? 0x10000 : 0);
  704. msg->addU32Fast(_PREHASH_Flags, flags);
  705. msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
  706. msg->addBoolFast(_PREHASH_Godlike, false); // Filled in on sim
  707. msg->nextBlockFast(_PREHASH_PositionData);
  708. msg->addU16Fast(_PREHASH_MinX, min_x);
  709. msg->addU16Fast(_PREHASH_MinY, min_y);
  710. msg->addU16Fast(_PREHASH_MaxX, max_x);
  711. msg->addU16Fast(_PREHASH_MaxY, max_y);
  712. gAgent.sendReliableMessage();
  713. if (mRequestLandForSale)
  714. {
  715. msg->newMessageFast(_PREHASH_MapBlockRequest);
  716. msg->nextBlockFast(_PREHASH_AgentData);
  717. msg->addUUIDFast(_PREHASH_AgentID, gAgentID);
  718. msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
  719. msg->addU32Fast(_PREHASH_Flags, 2);
  720. msg->addU32Fast(_PREHASH_EstateID, 0); // Filled in on sim
  721. msg->addBoolFast(_PREHASH_Godlike, false); // Filled in on sim
  722. msg->nextBlockFast(_PREHASH_PositionData);
  723. msg->addU16Fast(_PREHASH_MinX, min_x);
  724. msg->addU16Fast(_PREHASH_MinY, min_y);
  725. msg->addU16Fast(_PREHASH_MaxX, max_x);
  726. msg->addU16Fast(_PREHASH_MaxY, max_y);
  727. gAgent.sendReliableMessage();
  728. }
  729. }
  730. //static
  731. void LLWorldMap::processMapLayerReply(LLMessageSystem* msg, void**)
  732. {
  733. LL_DEBUGS("WorldMap") << "Processing map layer reply from message system"
  734. << LL_ENDL;
  735. U32 agent_flags;
  736. msg->getU32Fast(_PREHASH_AgentData, _PREHASH_Flags, agent_flags);
  737. if (agent_flags >= (U32)MAP_SIM_IMAGE_TYPES)
  738. {
  739. llwarns << "Invalid map image layer returned: " << agent_flags
  740. << llendl;
  741. return;
  742. }
  743. gWorldMap.mMapLayers[agent_flags].clear();
  744. LLTexUnit* unit0 = gGL.getTexUnit(0);
  745. #if 0
  746. bool use_web_map_tiles = useWebMapTiles();
  747. #endif
  748. bool adjust = false;
  749. S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_LayerData);
  750. for (S32 block = 0; block < num_blocks; ++block)
  751. {
  752. LLWorldMapLayer new_layer;
  753. new_layer.mLayerDefined = true;
  754. msg->getUUIDFast(_PREHASH_LayerData, _PREHASH_ImageID,
  755. new_layer.mLayerImageID, block);
  756. U32 left, right, top, bottom;
  757. msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Left, left, block);
  758. msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Right, right, block);
  759. msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Top, top, block);
  760. msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Bottom, bottom, block);
  761. #if 0 // No good... Maybe using of level 2 and higher web maps ?
  762. if (use_web_map_tiles)
  763. {
  764. new_layer.mLayerImage = loadObjectsTile(left, bottom);
  765. }
  766. else
  767. #endif
  768. new_layer.mLayerImage =
  769. LLViewerTextureManager::getFetchedTexture(new_layer.mLayerImageID,
  770. FTT_MAP_TILE, MIPMAP_YES,
  771. LLGLTexture::BOOST_MAP,
  772. LLViewerTexture::LOD_TEXTURE);
  773. unit0->bind(new_layer.mLayerImage.get());
  774. new_layer.mLayerImage->setAddressMode(LLTexUnit::TAM_CLAMP);
  775. new_layer.mLayerExtents.mLeft = left;
  776. new_layer.mLayerExtents.mRight = right;
  777. new_layer.mLayerExtents.mBottom = bottom;
  778. new_layer.mLayerExtents.mTop = top;
  779. F32 x_meters = F32(left * REGION_WIDTH_UNITS);
  780. F32 y_meters = F32(bottom * REGION_WIDTH_UNITS);
  781. if (gWorldMap.extendAABB((U32)x_meters, (U32)y_meters,
  782. U32(x_meters + REGION_WIDTH_UNITS *
  783. new_layer.mLayerExtents.getWidth()),
  784. U32(y_meters + REGION_WIDTH_UNITS *
  785. new_layer.mLayerExtents.getHeight())))
  786. {
  787. adjust = true;
  788. }
  789. gWorldMap.mMapLayers[agent_flags].push_back(new_layer);
  790. }
  791. gWorldMap.mMapLoaded[agent_flags] = true;
  792. if (adjust && gFloaterWorldMapp)
  793. {
  794. gFloaterWorldMapp->adjustZoomSliderBounds();
  795. }
  796. }
  797. //static
  798. bool LLWorldMap::useWebMapTiles()
  799. {
  800. static LLCachedControl<bool> use_web_map_tiles(gSavedSettings,
  801. "UseWebMapTiles");
  802. return use_web_map_tiles && (gIsInSecondLife || sGotMapURL) &&
  803. !sMapURL.empty() && gWorldMap.mCurrentMap == 0;
  804. }
  805. //static
  806. LLPointer<LLViewerFetchedTexture> LLWorldMap::loadObjectsTile(U32 grid_x,
  807. U32 grid_y)
  808. {
  809. // Get the grid coordinates
  810. std::string imageurl = sMapURL + llformat("map-1-%d-%d-objects.jpg",
  811. grid_x, grid_y);
  812. LLPointer<LLViewerFetchedTexture> texp =
  813. LLViewerTextureManager::getFetchedTextureFromUrl(imageurl,
  814. FTT_MAP_TILE, true,
  815. LLGLTexture::BOOST_MAP,
  816. LLViewerTexture::LOD_TEXTURE);
  817. // Return the smart pointer
  818. return texp;
  819. }
  820. //static
  821. void LLWorldMap::processMapBlockReply(LLMessageSystem* msg, void**)
  822. {
  823. if (!gFloaterWorldMapp) return;
  824. U32 agent_flags;
  825. msg->getU32Fast(_PREHASH_AgentData, _PREHASH_Flags, agent_flags);
  826. if (agent_flags >= (U32)MAP_SIM_IMAGE_TYPES)
  827. {
  828. llwarns << "Invalid map image type returned, layer = " << agent_flags
  829. << llendl;
  830. return;
  831. }
  832. S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_Data);
  833. bool found_null_sim = false;
  834. bool adjust = false;
  835. for (S32 block = 0; block < num_blocks; ++block)
  836. {
  837. U16 x_regions, y_regions;
  838. msg->getU16Fast(_PREHASH_Data, _PREHASH_X, x_regions, block);
  839. msg->getU16Fast(_PREHASH_Data, _PREHASH_Y, y_regions, block);
  840. std::string name;
  841. msg->getStringFast(_PREHASH_Data, _PREHASH_Name, name, block);
  842. U8 accesscode;
  843. msg->getU8Fast(_PREHASH_Data, _PREHASH_Access, accesscode, block);
  844. U32 region_flags;
  845. msg->getU32Fast(_PREHASH_Data, _PREHASH_RegionFlags, region_flags, block);
  846. LLUUID image_id;
  847. msg->getUUIDFast(_PREHASH_Data, _PREHASH_MapImageID, image_id, block);
  848. // OpenSim bug. BlockRequest can return sims without names with an
  849. // accesscode that is not 255. Skip if this has happened.
  850. if (name.empty() && accesscode != 255)
  851. {
  852. continue;
  853. }
  854. // Variable region size support
  855. U16 x_size = 0;
  856. U16 y_size = 0;
  857. if (msg->getNumberOfBlocksFast(_PREHASH_Size) > 0)
  858. {
  859. msg->getU16Fast(_PREHASH_Size, _PREHASH_SizeX, x_size, block);
  860. msg->getU16Fast(_PREHASH_Size, _PREHASH_SizeY, y_size, block);
  861. if (x_size == 0 || x_size % 16 != 0 || y_size % 16 != 0)
  862. {
  863. x_size = y_size = 0;
  864. }
  865. }
  866. U32 x_meters = (U32)x_regions * REGION_WIDTH_UNITS;
  867. U32 y_meters = (U32)y_regions * REGION_WIDTH_UNITS;
  868. U64 handle = to_region_handle(x_meters, y_meters);
  869. if (accesscode == 255)
  870. {
  871. // This region does not exist
  872. if (gWorldMap.isTrackedUnknownLocation(x_meters, y_meters))
  873. {
  874. // We were tracking this location, but it does not exist
  875. gWorldMap.mInvalidLocation = true;
  876. }
  877. found_null_sim = true;
  878. }
  879. else
  880. {
  881. if (gWorldMap.extendAABB(x_meters, y_meters,
  882. x_meters + REGION_WIDTH_UNITS,
  883. y_meters + REGION_WIDTH_UNITS))
  884. {
  885. adjust = true;
  886. }
  887. LLSimInfo* siminfo;
  888. sim_info_map_t::iterator iter = gWorldMap.mSimInfoMap.find(handle);
  889. if (iter != gWorldMap.mSimInfoMap.end())
  890. {
  891. siminfo = iter->second;
  892. }
  893. else
  894. {
  895. siminfo = new LLSimInfo();
  896. gWorldMap.mSimInfoMap[handle] = siminfo;
  897. }
  898. siminfo->mHandle = handle;
  899. siminfo->mName.assign(name);
  900. siminfo->mAccess = accesscode;
  901. siminfo->mRegionFlags = region_flags;
  902. siminfo->mMapImageID[agent_flags] = image_id;
  903. // Variable region size support
  904. if (x_size && y_size)
  905. {
  906. siminfo->setSize(x_size, y_size);
  907. }
  908. if (siminfo->mMapImageID[2].isNull())
  909. {
  910. siminfo->mOverlayImage = NULL;
  911. }
  912. if (gWorldMap.isTrackedUnknownLocation(x_meters, y_meters))
  913. {
  914. if (siminfo->mAccess == SIM_ACCESS_DOWN)
  915. {
  916. // We were tracking this location, but it does not exist
  917. gWorldMap.mInvalidLocation = true;
  918. }
  919. else
  920. {
  921. // We were tracking this location, and it does exist
  922. if (gFloaterWorldMapp)
  923. {
  924. gFloaterWorldMapp->trackLocation(gWorldMap.mUnknownLocation);
  925. }
  926. // Try another TP method...
  927. if (gWorldMap.mIsTrackingDoubleClick)
  928. {
  929. LLVector3d pos_global =
  930. gTracker.getTrackedPositionGlobal();
  931. gAgent.teleportViaLocation(pos_global);
  932. }
  933. }
  934. }
  935. }
  936. if (gWorldMap.mSLURLCallback)
  937. {
  938. // Server returns definitive capitalization, SLURL might not have
  939. // that.
  940. if (gWorldMap.mSLURLRegionHandle == handle ||
  941. LLStringUtil::compareInsensitive(gWorldMap.mSLURLRegionName,
  942. name) == 0)
  943. {
  944. url_callback_t callback = gWorldMap.mSLURLCallback;
  945. gWorldMap.mSLURLCallback = NULL;
  946. gWorldMap.mSLURLRegionName.clear();
  947. gWorldMap.mSLURLRegionHandle = 0;
  948. callback(handle, gWorldMap.mSLURL, image_id,
  949. gWorldMap.mSLURLTeleport);
  950. }
  951. }
  952. }
  953. if (adjust)
  954. {
  955. gFloaterWorldMapp->adjustZoomSliderBounds();
  956. }
  957. gFloaterWorldMapp->updateSims(found_null_sim);
  958. }
  959. //static
  960. void LLWorldMap::processMapItemReply(LLMessageSystem* msg, void**)
  961. {
  962. U32 type;
  963. msg->getU32Fast(_PREHASH_RequestData, _PREHASH_ItemType, type);
  964. static LLCachedControl<std::string> dfmt(gSavedSettings,
  965. "ShortDateFormat");
  966. static LLCachedControl<std::string> tfmt(gSavedSettings,
  967. "ShortTimeFormat");
  968. std::string time_format = dfmt;
  969. time_format += ' ';
  970. time_format += tfmt;
  971. S32 num_blocks = msg->getNumberOfBlocks("Data");
  972. for (S32 block = 0; block < num_blocks; ++block)
  973. {
  974. U32 x, y;
  975. msg->getU32Fast(_PREHASH_Data, _PREHASH_X, x, block);
  976. msg->getU32Fast(_PREHASH_Data, _PREHASH_Y, y, block);
  977. std::string name;
  978. msg->getStringFast(_PREHASH_Data, _PREHASH_Name, name, block);
  979. LLUUID uuid;
  980. msg->getUUIDFast(_PREHASH_Data, _PREHASH_ID, uuid, block);
  981. S32 extra, extra2;
  982. msg->getS32Fast(_PREHASH_Data, _PREHASH_Extra, extra, block);
  983. msg->getS32Fast(_PREHASH_Data, _PREHASH_Extra2, extra2, block);
  984. F32 world_x = (F32)x;
  985. x /= REGION_WIDTH_UNITS;
  986. F32 world_y = (F32)y;
  987. y /= REGION_WIDTH_UNITS;
  988. LLItemInfo new_item(world_x, world_y, name, uuid, extra, extra2);
  989. U64 handle = new_item.mRegionHandle;
  990. LLSimInfo* siminfo = gWorldMap.simInfoFromHandle(handle);
  991. switch (type)
  992. {
  993. case MAP_ITEM_TELEHUB:
  994. {
  995. // Telehub color, store in extra as 4 U8's
  996. U8* color = (U8*)&new_item.mExtra;
  997. F32 red = fmodf((F32)x * 0.11f, 1.f) * 0.8f;
  998. F32 green = fmodf((F32)y * 0.11f, 1.f) * 0.8f;
  999. F32 blue = fmodf(1.5f * (F32)(x + y) * 0.11f, 1.f) * 0.8f;
  1000. F32 add_amt = x % 2 ? 0.15f : -0.15f;
  1001. add_amt += y % 2 ? -0.15f : 0.15f;
  1002. color[0] = U8((red + add_amt) * 255);
  1003. color[1] = U8((green + add_amt) * 255);
  1004. color[2] = U8((blue + add_amt) * 255);
  1005. color[3] = 255;
  1006. // extra2 specifies whether this is an infohub or a telehub.
  1007. if (extra2)
  1008. {
  1009. gWorldMap.mInfohubs.push_back(new_item);
  1010. }
  1011. else
  1012. {
  1013. gWorldMap.mTelehubs.push_back(new_item);
  1014. }
  1015. break;
  1016. }
  1017. case MAP_ITEM_PG_EVENT:
  1018. case MAP_ITEM_MATURE_EVENT:
  1019. case MAP_ITEM_ADULT_EVENT:
  1020. {
  1021. new_item.mToolTip =
  1022. LLGridManager::getTimeStamp(extra, time_format);
  1023. // *HACK: store Z in extra2
  1024. new_item.mPosGlobal.mdV[VZ] = (F64)extra2;
  1025. if (type == MAP_ITEM_PG_EVENT)
  1026. {
  1027. gWorldMap.mPGEvents.push_back(new_item);
  1028. }
  1029. else if (type == MAP_ITEM_MATURE_EVENT)
  1030. {
  1031. gWorldMap.mMatureEvents.push_back(new_item);
  1032. }
  1033. else if (type == MAP_ITEM_ADULT_EVENT)
  1034. {
  1035. gWorldMap.mAdultEvents.push_back(new_item);
  1036. }
  1037. break;
  1038. }
  1039. case MAP_ITEM_LAND_FOR_SALE:
  1040. case MAP_ITEM_LAND_FOR_SALE_ADULT:
  1041. {
  1042. new_item.mToolTip = llformat("%d m2 L$%d", new_item.mExtra,
  1043. new_item.mExtra2);
  1044. if (type == MAP_ITEM_LAND_FOR_SALE)
  1045. {
  1046. gWorldMap.mLandForSale.push_back(new_item);
  1047. }
  1048. else if (type == MAP_ITEM_LAND_FOR_SALE_ADULT)
  1049. {
  1050. gWorldMap.mLandForSaleAdult.push_back(new_item);
  1051. }
  1052. break;
  1053. }
  1054. case MAP_ITEM_AGENT_LOCATIONS:
  1055. {
  1056. if (!siminfo)
  1057. {
  1058. llinfos << "Sim info missing for "
  1059. << new_item.mPosGlobal.mdV[0]
  1060. << ", " << new_item.mPosGlobal.mdV[1]
  1061. << llendl;
  1062. break;
  1063. }
  1064. LL_DEBUGS("WorldMap") << "New Location: " << new_item.mName
  1065. << LL_ENDL;
  1066. item_info_list_t& agentcounts =
  1067. gWorldMap.mAgentLocationsMap[handle];
  1068. // Find the last item in the list with a different name and
  1069. // erase them
  1070. item_info_list_t::iterator lastiter;
  1071. item_info_list_t::iterator end = agentcounts.end();
  1072. for (lastiter = agentcounts.begin(); lastiter != end;
  1073. ++lastiter)
  1074. {
  1075. const LLItemInfo& info = *lastiter;
  1076. if (info.mName == new_item.mName)
  1077. {
  1078. break;
  1079. }
  1080. }
  1081. if (lastiter != agentcounts.begin())
  1082. {
  1083. agentcounts.erase(agentcounts.begin(), lastiter);
  1084. }
  1085. // Now append the new location
  1086. if (new_item.mExtra > 0)
  1087. {
  1088. agentcounts.push_back(new_item);
  1089. }
  1090. break;
  1091. }
  1092. case MAP_ITEM_CLASSIFIED: // Deprecated, no longer used.
  1093. default:
  1094. break;
  1095. }
  1096. }
  1097. }
  1098. void LLWorldMap::dump()
  1099. {
  1100. for (sim_info_map_t::iterator it = mSimInfoMap.begin(),
  1101. end = mSimInfoMap.end();
  1102. it != end; ++it)
  1103. {
  1104. U64 handle = it->first;
  1105. LLSimInfo* info = it->second;
  1106. U32 x_pos, y_pos;
  1107. from_region_handle(handle, &x_pos, &y_pos);
  1108. llinfos << info->mName << " (" << x_pos << "," << y_pos
  1109. << ") - Access: " << (S32)info->mAccess
  1110. << " - Flags: " << std::hex << info->mRegionFlags << std::dec;
  1111. LLViewerFetchedTexture* texp = info->mCurrentImage[mCurrentMap].get();
  1112. if (texp)
  1113. {
  1114. llcont << " - Image layer: " << mCurrentMap
  1115. << " - Image: discard: " << (S32)texp->getDiscardLevel()
  1116. << " - full width: " << texp->getWidth(0)
  1117. << " - full height: " << texp->getHeight(0)
  1118. << " - max virtual size: " << texp->getMaxVirtualSize()
  1119. << " - max discard: " << (S32)texp->getMaxDiscardLevel();
  1120. }
  1121. llcont << llendl;
  1122. }
  1123. }
  1124. bool LLWorldMap::extendAABB(U32 min_x, U32 min_y, U32 max_x, U32 max_y)
  1125. {
  1126. bool rv = false;
  1127. if (min_x < mMinX)
  1128. {
  1129. rv = true;
  1130. mMinX = min_x;
  1131. }
  1132. if (min_y < mMinY)
  1133. {
  1134. rv = true;
  1135. mMinY = min_y;
  1136. }
  1137. if (max_x > mMaxX)
  1138. {
  1139. rv = true;
  1140. mMaxX = max_x;
  1141. }
  1142. if (max_y > mMaxY)
  1143. {
  1144. rv = true;
  1145. mMaxY = max_y;
  1146. }
  1147. LL_DEBUGS("WorldMap") << "World map AABB: (" << mMinX << ", " << mMinY
  1148. << "), (" << mMaxX << ", " << mMaxY << ")"
  1149. << LL_ENDL;
  1150. return rv;
  1151. }