lltoolbrush.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:19k
源码类别:

游戏引擎

开发平台:

C++ Builder

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