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

/indra/newview/lltoolbrush.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 676 lines | 494 code | 77 blank | 105 comment | 70 complexity | ad2c211e5b354caadf32f69d424e1a45 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file lltoolbrush.cpp
  3. * @brief Implementation of the toolbrushes
  4. *
  5. * $LicenseInfo:firstyear=2001&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 "llviewerprecompiledheaders.h"
  27. #include "lltoolbrush.h"
  28. #include "lltoolselectland.h"
  29. // library headers
  30. #include "llgl.h"
  31. #include "llnotificationsutil.h"
  32. #include "llrender.h"
  33. #include "message.h"
  34. #include "llagent.h"
  35. #include "llcallbacklist.h"
  36. #include "llviewercontrol.h"
  37. #include "llfloatertools.h"
  38. #include "llregionposition.h"
  39. #include "llstatusbar.h"
  40. #include "llsurface.h"
  41. #include "llsurfacepatch.h"
  42. #include "lltoolmgr.h"
  43. #include "llui.h"
  44. #include "llviewerparcelmgr.h"
  45. #include "llviewerparceloverlay.h"
  46. #include "llviewerregion.h"
  47. #include "llviewerwindow.h"
  48. #include "llworld.h"
  49. #include "llappviewer.h"
  50. #include "llparcel.h"
  51. #include "llglheaders.h"
  52. const std::string REGION_BLOCKS_TERRAFORM_MSG = "This region does not allow terraforming.\n"
  53. "You will need to buy land in another part of the world to terraform it.";
  54. ///============================================================================
  55. /// Local function declarations, constants, enums, and typedefs
  56. ///============================================================================
  57. const S32 LAND_BRUSH_SIZE_COUNT = 3;
  58. const F32 LAND_BRUSH_SIZE[LAND_BRUSH_SIZE_COUNT] = {1.0f, 2.0f, 4.0f};
  59. const S32 LAND_STEPS = 3;
  60. const F32 LAND_METERS_PER_SECOND = 1.0f;
  61. enum
  62. {
  63. E_LAND_LEVEL = 0,
  64. E_LAND_RAISE = 1,
  65. E_LAND_LOWER = 2,
  66. E_LAND_SMOOTH = 3,
  67. E_LAND_NOISE = 4,
  68. E_LAND_REVERT = 5,
  69. E_LAND_INVALID = 6,
  70. };
  71. const LLColor4 OVERLAY_COLOR(1.0f, 1.0f, 1.0f, 1.0f);
  72. ///============================================================================
  73. /// Class LLToolBrushLand
  74. ///============================================================================
  75. // constructor
  76. LLToolBrushLand::LLToolBrushLand()
  77. : LLTool(std::string("Land")),
  78. mStartingZ( 0.0f ),
  79. mMouseX( 0 ),
  80. mMouseY(0),
  81. mGotHover(FALSE),
  82. mBrushSelected(FALSE)
  83. {
  84. mBrushSize = gSavedSettings.getF32("LandBrushSize");
  85. }
  86. U8 LLToolBrushLand::getBrushIndex()
  87. {
  88. // find the best index for desired size
  89. // (compatibility with old sims, brush_index is now depricated - DEV-8252)
  90. U8 index = 0;
  91. for (U8 i = 0; i < LAND_BRUSH_SIZE_COUNT; i++)
  92. {
  93. if (mBrushSize > LAND_BRUSH_SIZE[i])
  94. {
  95. index = i;
  96. }
  97. }
  98. return index;
  99. }
  100. void LLToolBrushLand::modifyLandAtPointGlobal(const LLVector3d &pos_global,
  101. MASK mask)
  102. {
  103. S32 radioAction = gSavedSettings.getS32("RadioLandBrushAction");
  104. mLastAffectedRegions.clear();
  105. determineAffectedRegions(mLastAffectedRegions, pos_global);
  106. for(region_list_t::iterator iter = mLastAffectedRegions.begin();
  107. iter != mLastAffectedRegions.end(); ++iter)
  108. {
  109. LLViewerRegion* regionp = *iter;
  110. //BOOL is_changed = FALSE;
  111. LLVector3 pos_region = regionp->getPosRegionFromGlobal(pos_global);
  112. LLSurface &land = regionp->getLand();
  113. char action = E_LAND_LEVEL;
  114. switch (radioAction)
  115. {
  116. case 0:
  117. // // average toward mStartingZ
  118. action = E_LAND_LEVEL;
  119. break;
  120. case 1:
  121. action = E_LAND_RAISE;
  122. break;
  123. case 2:
  124. action = E_LAND_LOWER;
  125. break;
  126. case 3:
  127. action = E_LAND_SMOOTH;
  128. break;
  129. case 4:
  130. action = E_LAND_NOISE;
  131. break;
  132. case 5:
  133. action = E_LAND_REVERT;
  134. break;
  135. default:
  136. action = E_LAND_INVALID;
  137. break;
  138. }
  139. // Don't send a message to the region if nothing changed.
  140. //if(!is_changed) continue;
  141. // Now to update the patch information so it will redraw correctly.
  142. LLSurfacePatch *patchp= land.resolvePatchRegion(pos_region);
  143. if (patchp)
  144. {
  145. patchp->dirtyZ();
  146. }
  147. // Also force the property lines to update, normals to recompute, etc.
  148. regionp->forceUpdate();
  149. // tell the simulator what we've done
  150. F32 seconds = (1.0f / gFPSClamped) * gSavedSettings.getF32("LandBrushForce");
  151. F32 x_pos = (F32)pos_region.mV[VX];
  152. F32 y_pos = (F32)pos_region.mV[VY];
  153. LLMessageSystem* msg = gMessageSystem;
  154. msg->newMessageFast(_PREHASH_ModifyLand);
  155. msg->nextBlockFast(_PREHASH_AgentData);
  156. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  157. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  158. msg->nextBlockFast(_PREHASH_ModifyBlock);
  159. msg->addU8Fast(_PREHASH_Action, (U8)action);
  160. msg->addU8Fast(_PREHASH_BrushSize, getBrushIndex());
  161. msg->addF32Fast(_PREHASH_Seconds, seconds);
  162. msg->addF32Fast(_PREHASH_Height, mStartingZ);
  163. msg->nextBlockFast(_PREHASH_ParcelData);
  164. msg->addS32Fast(_PREHASH_LocalID, -1);
  165. msg->addF32Fast(_PREHASH_West, x_pos );
  166. msg->addF32Fast(_PREHASH_South, y_pos );
  167. msg->addF32Fast(_PREHASH_East, x_pos );
  168. msg->addF32Fast(_PREHASH_North, y_pos );
  169. msg->nextBlock("ModifyBlockExtended");
  170. msg->addF32("BrushSize", mBrushSize);
  171. msg->sendMessage(regionp->getHost());
  172. }
  173. }
  174. void LLToolBrushLand::modifyLandInSelectionGlobal()
  175. {
  176. if (LLViewerParcelMgr::getInstance()->selectionEmpty())
  177. {
  178. return;
  179. }
  180. if (LLToolMgr::getInstance()->getCurrentTool() == LLToolSelectLand::getInstance())
  181. {
  182. // selecting land, don't do anything
  183. return;
  184. }
  185. LLVector3d min;
  186. LLVector3d max;
  187. LLViewerParcelMgr::getInstance()->getSelection(min, max);
  188. S32 radioAction = gSavedSettings.getS32("RadioLandBrushAction");
  189. mLastAffectedRegions.clear();
  190. determineAffectedRegions(mLastAffectedRegions, LLVector3d(min.mdV[VX], min.mdV[VY], 0));
  191. determineAffectedRegions(mLastAffectedRegions, LLVector3d(min.mdV[VX], max.mdV[VY], 0));
  192. determineAffectedRegions(mLastAffectedRegions, LLVector3d(max.mdV[VX], min.mdV[VY], 0));
  193. determineAffectedRegions(mLastAffectedRegions, LLVector3d(max.mdV[VX], max.mdV[VY], 0));
  194. LLRegionPosition mid_point_region((min + max) * 0.5);
  195. LLViewerRegion* center_region = mid_point_region.getRegion();
  196. if (center_region)
  197. {
  198. LLVector3 pos_region = mid_point_region.getPositionRegion();
  199. U32 grids = center_region->getLand().mGridsPerEdge;
  200. S32 i = llclamp( (S32)pos_region.mV[VX], 0, (S32)grids );
  201. S32 j = llclamp( (S32)pos_region.mV[VY], 0, (S32)grids );
  202. mStartingZ = center_region->getLand().getZ(i+j*grids);
  203. }
  204. else
  205. {
  206. mStartingZ = 0.f;
  207. }
  208. // Stop if our selection include a no-terraform region
  209. for(region_list_t::iterator iter = mLastAffectedRegions.begin();
  210. iter != mLastAffectedRegions.end(); ++iter)
  211. {
  212. LLViewerRegion* regionp = *iter;
  213. if (!canTerraform(regionp))
  214. {
  215. alertNoTerraform(regionp);
  216. return;
  217. }
  218. }
  219. for(region_list_t::iterator iter = mLastAffectedRegions.begin();
  220. iter != mLastAffectedRegions.end(); ++iter)
  221. {
  222. LLViewerRegion* regionp = *iter;
  223. //BOOL is_changed = FALSE;
  224. LLVector3 min_region = regionp->getPosRegionFromGlobal(min);
  225. LLVector3 max_region = regionp->getPosRegionFromGlobal(max);
  226. min_region.clamp(0.f, regionp->getWidth());
  227. max_region.clamp(0.f, regionp->getWidth());
  228. F32 seconds = gSavedSettings.getF32("LandBrushForce");
  229. LLSurface &land = regionp->getLand();
  230. char action = E_LAND_LEVEL;
  231. switch (radioAction)
  232. {
  233. case 0:
  234. // // average toward mStartingZ
  235. action = E_LAND_LEVEL;
  236. seconds *= 0.25f;
  237. break;
  238. case 1:
  239. action = E_LAND_RAISE;
  240. seconds *= 0.25f;
  241. break;
  242. case 2:
  243. action = E_LAND_LOWER;
  244. seconds *= 0.25f;
  245. break;
  246. case 3:
  247. action = E_LAND_SMOOTH;
  248. seconds *= 5.0f;
  249. break;
  250. case 4:
  251. action = E_LAND_NOISE;
  252. seconds *= 0.5f;
  253. break;
  254. case 5:
  255. action = E_LAND_REVERT;
  256. seconds = 0.5f;
  257. break;
  258. default:
  259. //action = E_LAND_INVALID;
  260. //seconds = 0.0f;
  261. return;
  262. break;
  263. }
  264. // Don't send a message to the region if nothing changed.
  265. //if(!is_changed) continue;
  266. // Now to update the patch information so it will redraw correctly.
  267. LLSurfacePatch *patchp= land.resolvePatchRegion(min_region);
  268. if (patchp)
  269. {
  270. patchp->dirtyZ();
  271. }
  272. // Also force the property lines to update, normals to recompute, etc.
  273. regionp->forceUpdate();
  274. // tell the simulator what we've done
  275. LLMessageSystem* msg = gMessageSystem;
  276. msg->newMessageFast(_PREHASH_ModifyLand);
  277. msg->nextBlockFast(_PREHASH_AgentData);
  278. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  279. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  280. msg->nextBlockFast(_PREHASH_ModifyBlock);
  281. msg->addU8Fast(_PREHASH_Action, (U8)action);
  282. msg->addU8Fast(_PREHASH_BrushSize, getBrushIndex());
  283. msg->addF32Fast(_PREHASH_Seconds, seconds);
  284. msg->addF32Fast(_PREHASH_Height, mStartingZ);
  285. BOOL parcel_selected = LLViewerParcelMgr::getInstance()->getParcelSelection()->getWholeParcelSelected();
  286. LLParcel* selected_parcel = LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel();
  287. if (parcel_selected && selected_parcel)
  288. {
  289. msg->nextBlockFast(_PREHASH_ParcelData);
  290. msg->addS32Fast(_PREHASH_LocalID, selected_parcel->getLocalID());
  291. msg->addF32Fast(_PREHASH_West, min_region.mV[VX] );
  292. msg->addF32Fast(_PREHASH_South, min_region.mV[VY] );
  293. msg->addF32Fast(_PREHASH_East, max_region.mV[VX] );
  294. msg->addF32Fast(_PREHASH_North, max_region.mV[VY] );
  295. }
  296. else
  297. {
  298. msg->nextBlockFast(_PREHASH_ParcelData);
  299. msg->addS32Fast(_PREHASH_LocalID, -1);
  300. msg->addF32Fast(_PREHASH_West, min_region.mV[VX] );
  301. msg->addF32Fast(_PREHASH_South, min_region.mV[VY] );
  302. msg->addF32Fast(_PREHASH_East, max_region.mV[VX] );
  303. msg->addF32Fast(_PREHASH_North, max_region.mV[VY] );
  304. }
  305. msg->nextBlock("ModifyBlockExtended");
  306. msg->addF32("BrushSize", mBrushSize);
  307. msg->sendMessage(regionp->getHost());
  308. }
  309. }
  310. void LLToolBrushLand::brush( void )
  311. {
  312. LLVector3d spot;
  313. if( gViewerWindow->mousePointOnLandGlobal( mMouseX, mMouseY, &spot ) )
  314. {
  315. // Round to nearest X,Y grid
  316. spot.mdV[VX] = floor( spot.mdV[VX] + 0.5 );
  317. spot.mdV[VY] = floor( spot.mdV[VY] + 0.5 );
  318. modifyLandAtPointGlobal(spot, gKeyboard->currentMask(TRUE));
  319. }
  320. }
  321. BOOL LLToolBrushLand::handleMouseDown(S32 x, S32 y, MASK mask)
  322. {
  323. BOOL handled = FALSE;
  324. // Find the z value of the initial click.
  325. LLVector3d spot;
  326. if( gViewerWindow->mousePointOnLandGlobal( x, y, &spot ) )
  327. {
  328. // Round to nearest X,Y grid
  329. spot.mdV[VX] = floor( spot.mdV[VX] + 0.5 );
  330. spot.mdV[VY] = floor( spot.mdV[VY] + 0.5 );
  331. LLRegionPosition region_position( spot );
  332. LLViewerRegion* regionp = region_position.getRegion();
  333. if (!canTerraform(regionp))
  334. {
  335. alertNoTerraform(regionp);
  336. return TRUE;
  337. }
  338. LLVector3 pos_region = region_position.getPositionRegion();
  339. U32 grids = regionp->getLand().mGridsPerEdge;
  340. S32 i = llclamp( (S32)pos_region.mV[VX], 0, (S32)grids );
  341. S32 j = llclamp( (S32)pos_region.mV[VY], 0, (S32)grids );
  342. mStartingZ = regionp->getLand().getZ(i+j*grids);
  343. mMouseX = x;
  344. mMouseY = y;
  345. gIdleCallbacks.addFunction( &LLToolBrushLand::onIdle, (void*)this );
  346. setMouseCapture( TRUE );
  347. LLViewerParcelMgr::getInstance()->setSelectionVisible(FALSE);
  348. handled = TRUE;
  349. }
  350. return handled;
  351. }
  352. BOOL LLToolBrushLand::handleHover( S32 x, S32 y, MASK mask )
  353. {
  354. lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolBrushLand ("
  355. << (hasMouseCapture() ? "active":"inactive")
  356. << ")" << llendl;
  357. mMouseX = x;
  358. mMouseY = y;
  359. mGotHover = TRUE;
  360. gViewerWindow->setCursor(UI_CURSOR_TOOLLAND);
  361. return TRUE;
  362. }
  363. BOOL LLToolBrushLand::handleMouseUp(S32 x, S32 y, MASK mask)
  364. {
  365. BOOL handled = FALSE;
  366. mLastAffectedRegions.clear();
  367. if( hasMouseCapture() )
  368. {
  369. // Release the mouse
  370. setMouseCapture( FALSE );
  371. LLViewerParcelMgr::getInstance()->setSelectionVisible(TRUE);
  372. gIdleCallbacks.deleteFunction( &LLToolBrushLand::onIdle, (void*)this );
  373. handled = TRUE;
  374. }
  375. return handled;
  376. }
  377. void LLToolBrushLand::handleSelect()
  378. {
  379. gEditMenuHandler = this;
  380. gFloaterTools->setStatusText("modifyland");
  381. // if (!mBrushSelected)
  382. {
  383. mBrushSelected = TRUE;
  384. }
  385. }
  386. void LLToolBrushLand::handleDeselect()
  387. {
  388. if( gEditMenuHandler == this )
  389. {
  390. gEditMenuHandler = NULL;
  391. }
  392. LLViewerParcelMgr::getInstance()->setSelectionVisible(TRUE);
  393. mBrushSelected = FALSE;
  394. }
  395. // Draw the area that will be affected.
  396. void LLToolBrushLand::render()
  397. {
  398. if(mGotHover)
  399. {
  400. //llinfos << "LLToolBrushLand::render()" << llendl;
  401. LLVector3d spot;
  402. if(gViewerWindow->mousePointOnLandGlobal(mMouseX, mMouseY, &spot))
  403. {
  404. spot.mdV[VX] = floor( spot.mdV[VX] + 0.5 );
  405. spot.mdV[VY] = floor( spot.mdV[VY] + 0.5 );
  406. mBrushSize = gSavedSettings.getF32("LandBrushSize");
  407. region_list_t regions;
  408. determineAffectedRegions(regions, spot);
  409. // Now, for each region, render the overlay
  410. LLVector3 pos_world = gAgent.getRegion()->getPosRegionFromGlobal(spot);
  411. for(region_list_t::iterator iter = regions.begin();
  412. iter != regions.end(); ++iter)
  413. {
  414. LLViewerRegion* region = *iter;
  415. renderOverlay(region->getLand(),
  416. region->getPosRegionFromGlobal(spot),
  417. pos_world);
  418. }
  419. }
  420. mGotHover = FALSE;
  421. }
  422. }
  423. /*
  424. * Draw vertical lines from each vertex straight up in world space
  425. * with lengths indicating the current "strength" slider.
  426. * Decorate the tops and bottoms of the lines like this:
  427. *
  428. * Raise Revert
  429. * /|\ ___
  430. * | |
  431. * | |
  432. *
  433. * Rough Smooth
  434. * /|\ ___
  435. * | |
  436. * | |
  437. * \|/..........._|_
  438. *
  439. * Lower Flatten
  440. * | |
  441. * | |
  442. * \|/..........._|_
  443. */
  444. void LLToolBrushLand::renderOverlay(LLSurface& land, const LLVector3& pos_region,
  445. const LLVector3& pos_world)
  446. {
  447. gGL.matrixMode(LLRender::MM_MODELVIEW);
  448. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  449. LLGLDepthTest mDepthTest(GL_TRUE);
  450. gGL.pushMatrix();
  451. gGL.color4fv(OVERLAY_COLOR.mV);
  452. gGL.translatef(0.0f, 0.0f, 1.0f);
  453. S32 i = (S32) pos_region.mV[VX];
  454. S32 j = (S32) pos_region.mV[VY];
  455. S32 half_edge = llfloor(mBrushSize);
  456. S32 radioAction = gSavedSettings.getS32("RadioLandBrushAction");
  457. F32 force = gSavedSettings.getF32("LandBrushForce"); // .1 to 100?
  458. gGL.begin(LLRender::LINES);
  459. for(S32 di = -half_edge; di <= half_edge; di++)
  460. {
  461. if((i+di) < 0 || (i+di) >= (S32)land.mGridsPerEdge) continue;
  462. for(S32 dj = -half_edge; dj <= half_edge; dj++)
  463. {
  464. if( (j+dj) < 0 || (j+dj) >= (S32)land.mGridsPerEdge ) continue;
  465. const F32
  466. wx = pos_world.mV[VX] + di,
  467. wy = pos_world.mV[VY] + dj,
  468. wz = land.getZ((i+di)+(j+dj)*land.mGridsPerEdge),
  469. norm_dist = sqrt((float)di*di + dj*dj) / half_edge,
  470. force_scale = sqrt(2.f) - norm_dist, // 1 at center, 0 at corner
  471. wz2 = wz + .2 + (.2 + force/100) * force_scale, // top vertex
  472. tic = .075f; // arrowhead size
  473. // vertical line
  474. gGL.vertex3f(wx, wy, wz);
  475. gGL.vertex3f(wx, wy, wz2);
  476. if(radioAction == E_LAND_RAISE || radioAction == E_LAND_NOISE) // up arrow
  477. {
  478. gGL.vertex3f(wx, wy, wz2);
  479. gGL.vertex3f(wx+tic, wy, wz2-tic);
  480. gGL.vertex3f(wx, wy, wz2);
  481. gGL.vertex3f(wx-tic, wy, wz2-tic);
  482. }
  483. if(radioAction == E_LAND_LOWER || radioAction == E_LAND_NOISE) // down arrow
  484. {
  485. gGL.vertex3f(wx, wy, wz);
  486. gGL.vertex3f(wx+tic, wy, wz+tic);
  487. gGL.vertex3f(wx, wy, wz);
  488. gGL.vertex3f(wx-tic, wy, wz+tic);
  489. }
  490. if(radioAction == E_LAND_REVERT || radioAction == E_LAND_SMOOTH) // flat top
  491. {
  492. gGL.vertex3f(wx-tic, wy, wz2);
  493. gGL.vertex3f(wx+tic, wy, wz2);
  494. }
  495. if(radioAction == E_LAND_LEVEL || radioAction == E_LAND_SMOOTH) // flat bottom
  496. {
  497. gGL.vertex3f(wx-tic, wy, wz);
  498. gGL.vertex3f(wx+tic, wy, wz);
  499. }
  500. }
  501. }
  502. gGL.end();
  503. gGL.popMatrix();
  504. }
  505. void LLToolBrushLand::determineAffectedRegions(region_list_t& regions,
  506. const LLVector3d& spot ) const
  507. {
  508. LLVector3d corner(spot);
  509. corner.mdV[VX] -= (mBrushSize / 2);
  510. corner.mdV[VY] -= (mBrushSize / 2);
  511. LLViewerRegion* region = NULL;
  512. region = LLWorld::getInstance()->getRegionFromPosGlobal(corner);
  513. if(region && regions.find(region) == regions.end())
  514. {
  515. regions.insert(region);
  516. }
  517. corner.mdV[VY] += mBrushSize;
  518. region = LLWorld::getInstance()->getRegionFromPosGlobal(corner);
  519. if(region && regions.find(region) == regions.end())
  520. {
  521. regions.insert(region);
  522. }
  523. corner.mdV[VX] += mBrushSize;
  524. region = LLWorld::getInstance()->getRegionFromPosGlobal(corner);
  525. if(region && regions.find(region) == regions.end())
  526. {
  527. regions.insert(region);
  528. }
  529. corner.mdV[VY] -= mBrushSize;
  530. region = LLWorld::getInstance()->getRegionFromPosGlobal(corner);
  531. if(region && regions.find(region) == regions.end())
  532. {
  533. regions.insert(region);
  534. }
  535. }
  536. // static
  537. void LLToolBrushLand::onIdle( void* brush_tool )
  538. {
  539. LLToolBrushLand* self = reinterpret_cast<LLToolBrushLand*>(brush_tool);
  540. if( LLToolMgr::getInstance()->getCurrentTool() == self )
  541. {
  542. self->brush();
  543. }
  544. else
  545. {
  546. gIdleCallbacks.deleteFunction( &LLToolBrushLand::onIdle, self );
  547. }
  548. }
  549. void LLToolBrushLand::onMouseCaptureLost()
  550. {
  551. gIdleCallbacks.deleteFunction(&LLToolBrushLand::onIdle, this);
  552. }
  553. // static
  554. void LLToolBrushLand::undo()
  555. {
  556. for(region_list_t::iterator iter = mLastAffectedRegions.begin();
  557. iter != mLastAffectedRegions.end(); ++iter)
  558. {
  559. LLViewerRegion* regionp = *iter;
  560. gMessageSystem->newMessageFast(_PREHASH_UndoLand);
  561. gMessageSystem->nextBlockFast(_PREHASH_AgentData);
  562. gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
  563. gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  564. gMessageSystem->sendMessage(regionp->getHost());
  565. }
  566. }
  567. // static
  568. /*
  569. void LLToolBrushLand::redo()
  570. {
  571. for(region_list_t::iterator iter = mLastAffectedRegions.begin();
  572. iter != mLastAffectedRegions.end(); ++iter)
  573. {
  574. LLViewerRegion* regionp = *iter;
  575. gMessageSystem->newMessageFast(_PREHASH_RedoLand);
  576. gMessageSystem->nextBlockFast(_PREHASH_AgentData);
  577. gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
  578. gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  579. gMessageSystem->sendMessage(regionp->getHost());
  580. }
  581. }*/
  582. // static
  583. bool LLToolBrushLand::canTerraform(LLViewerRegion* regionp) const
  584. {
  585. if (!regionp) return false;
  586. if (regionp->canManageEstate()) return true;
  587. return !(regionp->getRegionFlags() & REGION_FLAGS_BLOCK_TERRAFORM);
  588. }
  589. // static
  590. void LLToolBrushLand::alertNoTerraform(LLViewerRegion* regionp)
  591. {
  592. if (!regionp) return;
  593. LLSD args;
  594. args["REGION"] = regionp->getName();
  595. LLNotificationsUtil::add("RegionNoTerraforming", args);
  596. }
  597. ///============================================================================
  598. /// Local function definitions
  599. ///============================================================================