guiMissionArea.cpp
Engine/source/gui/worldEditor/guiMissionArea.cpp
Public Functions
ConsoleDocClass(GuiMissionAreaCtrl , "@brief Visual representation of Mission Area <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Editor.\n\n</a>" "@internal" )
DefineEngineMethod(GuiMissionAreaCtrl , setMissionArea , void , (MissionArea *area) , "@brief Set the <a href="/coding/class/classmissionarea/">MissionArea</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">edit.\n\n</a>" )
DefineEngineMethod(GuiMissionAreaCtrl , updateTerrain , void , () , "@brief Update the terrain <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">bitmap.\n\n</a>" )
Detailed Description
Public Functions
ConsoleDocClass(GuiMissionAreaCtrl , "@brief Visual representation of Mission Area <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Editor.\n\n</a>" "@internal" )
DefineEngineMethod(GuiMissionAreaCtrl , setMissionArea , void , (MissionArea *area) , "@brief Set the <a href="/coding/class/classmissionarea/">MissionArea</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">edit.\n\n</a>" )
DefineEngineMethod(GuiMissionAreaCtrl , updateTerrain , void , () , "@brief Update the terrain <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">bitmap.\n\n</a>" )
IMPLEMENT_CONOBJECT(GuiMissionAreaCtrl )
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "gui/worldEditor/guiMissionArea.h" 25#include "console/consoleTypes.h" 26#include "console/engineAPI.h" 27#include "gfx/gfxDrawUtil.h" 28#include "gfx/primBuilder.h" 29#include "gfx/bitmap/gBitmap.h" 30#include "gui/3d/guiTSControl.h" 31#include "T3D/gameFunctions.h" 32#include "terrain/terrData.h" 33 34namespace { 35 F32 round_local(F32 val) 36 { 37 if(val >= 0.f) 38 { 39 F32 floor = mFloor(val); 40 if((val - floor) >= 0.5f) 41 return(floor + 1.f); 42 return(floor); 43 } 44 else 45 { 46 F32 ceil = mCeil(val); 47 if((val - ceil) <= -0.5f) 48 return(ceil - 1.f); 49 return(ceil); 50 } 51 } 52} 53 54IMPLEMENT_CONOBJECT(GuiMissionAreaCtrl); 55 56ConsoleDocClass( GuiMissionAreaCtrl, 57 "@brief Visual representation of Mission Area Editor.\n\n" 58 "@internal" 59); 60 61GuiMissionAreaCtrl::GuiMissionAreaCtrl() 62{ 63 mHandleBitmap = StringTable->EmptyString(); 64 mHandleTexture = NULL; 65 mHandleTextureSize = Point2I::Zero; 66 mHandleTextureHalfSize = Point2F::Zero; 67 68 mSquareBitmap = true; 69 70 mMissionArea = 0; 71 mTerrainBlock = 0; 72 73 mMissionBoundsColor.set(255,0,0); 74 mCameraColor.set(255,0,0); 75 76 mBlendStateBlock = NULL; 77 mSolidStateBlock = NULL; 78 79 mLastHitMode = Handle_None; 80 mSavedDrag = false; 81} 82 83GuiMissionAreaCtrl::~GuiMissionAreaCtrl() 84{ 85} 86 87//------------------------------------------------------------------------------ 88 89void GuiMissionAreaCtrl::initPersistFields() 90{ 91 addField( "squareBitmap", TypeBool, Offset(mSquareBitmap, GuiMissionAreaCtrl)); 92 93 addField( "handleBitmap", TypeFilename, Offset( mHandleBitmap, GuiMissionAreaCtrl ), 94 "Bitmap file for the mission area handles.\n"); 95 96 addField( "missionBoundsColor", TypeColorI, Offset(mMissionBoundsColor, GuiMissionAreaCtrl)); 97 addField( "cameraColor", TypeColorI, Offset(mCameraColor, GuiMissionAreaCtrl)); 98 99 Parent::initPersistFields(); 100} 101 102//------------------------------------------------------------------------------ 103 104bool GuiMissionAreaCtrl::onAdd() 105{ 106 if(!Parent::onAdd()) 107 return(false); 108 109 GFXStateBlockDesc desc; 110 desc.setCullMode(GFXCullNone); 111 desc.setZReadWrite(false); 112 desc.setBlend(false, GFXBlendOne, GFXBlendZero); 113 mSolidStateBlock = GFX->createStateBlock( desc ); 114 115 desc.setBlend(true, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha); 116 mBlendStateBlock = GFX->createStateBlock( desc ); 117 118 if (*mHandleBitmap) 119 { 120 mHandleTexture = GFXTexHandle( mHandleBitmap, &GFXTexturePersistentSRGBProfile, avar("%s() - mHandleTexture (line %d)", __FUNCTION__, __LINE__) ); 121 mHandleTextureSize = Point2I( mHandleTexture->getWidth(), mHandleTexture->getHeight() ); 122 mHandleTextureHalfSize = Point2F(mHandleTextureSize.x, mHandleTextureSize.y) * 0.5f; 123 } 124 else 125 { 126 mHandleTexture = NULL; 127 mHandleTextureSize = Point2I::Zero; 128 mHandleTextureHalfSize = Point2F::Zero; 129 } 130 131 return(true); 132} 133 134bool GuiMissionAreaCtrl::onWake() 135{ 136 if(!Parent::onWake()) 137 return(false); 138 139 //mMissionArea = const_cast<MissionArea*>(MissionArea::getServerObject()); 140 //if(!bool(mMissionArea)) 141 // Con::warnf(ConsoleLogEntry::General, "GuiMissionAreaCtrl::onWake: no MissionArea object."); 142 143 //mTerrainBlock = getTerrainObj(); 144 //if(!bool(mTerrainBlock)) 145 // Con::warnf(ConsoleLogEntry::General, "GuiMissionAreaCtrl::onWake: no TerrainBlock object."); 146 147 //if ( !bool(mMissionArea) || !bool(mTerrainBlock) ) 148 // return true; 149 150 updateTerrainBitmap(); 151 152 // make sure mission area is clamped 153 setArea(getArea()); 154 155 //onUpdate(); 156 setActive(true); 157 158 return(true); 159} 160 161void GuiMissionAreaCtrl::onSleep() 162{ 163 mTextureObject = NULL; 164 mMissionArea = 0; 165 mTerrainBlock = 0; 166 167 Parent::onSleep(); 168} 169 170//------------------------------------------------------------------------------ 171 172void GuiMissionAreaCtrl::onMouseUp(const GuiEvent & event) 173{ 174 if(!bool(mMissionArea)) 175 return; 176 177 RectI box; 178 getScreenMissionArea(box); 179 S32 hit = getHitHandles(event.mousePoint, box); 180 181 // set the current cursor 182 //updateCursor(hit); 183 mLastHitMode = hit; 184 185 if(mSavedDrag) 186 { 187 // Let the script get a chance at it. 188 Con::executef( this, "onMissionAreaModified" ); 189 } 190 mSavedDrag = false; 191} 192 193void GuiMissionAreaCtrl::onMouseDown(const GuiEvent & event) 194{ 195 if(!bool(mMissionArea)) 196 return; 197 198 RectI box; 199 getScreenMissionArea(box); 200 201 mLastHitMode = getHitHandles(event.mousePoint, box); 202 //if(mLastHitMode == Handle_Middle) 203 // setCursor(GrabCursor); 204 mLastMousePoint = event.mousePoint; 205} 206 207void GuiMissionAreaCtrl::onMouseMove(const GuiEvent & event) 208{ 209 if(!bool(mMissionArea)) 210 return; 211 212 RectI box; 213 getScreenMissionArea(box); 214 S32 hit = getHitHandles(event.mousePoint, box); 215 216 // set the current cursor... 217 //updateCursor(hit); 218 mLastHitMode = hit; 219} 220 221void GuiMissionAreaCtrl::onMouseDragged(const GuiEvent & event) 222{ 223 if(!bool(mMissionArea)) 224 return; 225 226 if(mLastHitMode == Handle_None) 227 return; 228 229 // If we haven't already saved, 230 // save an undo action to get back to this state, 231 // before we make any modifications. 232 if ( !mSavedDrag ) 233 { 234 submitUndo( "Modify Node" ); 235 mSavedDrag = true; 236 } 237 238 RectI box; 239 getScreenMissionArea(box); 240 Point2I mouseDiff(event.mousePoint.x - mLastMousePoint.x, 241 event.mousePoint.y - mLastMousePoint.y); 242 243 // what we drag'n? 244 RectI area = getArea(); 245 Point2I wp = screenDeltaToWorldDelta(mouseDiff); 246 247 if (mLastHitMode == Handle_Middle) 248 { 249 area.point += wp; 250 } 251 252 if (mLastHitMode & Handle_Left) 253 { 254 if ((area.extent.x - wp.x) >= 1) 255 { 256 area.point.x += wp.x; 257 area.extent.x -= wp.x; 258 } 259 } 260 261 if (mLastHitMode & Handle_Right) 262 { 263 if ((area.extent.x + wp.x) >= 1) 264 { 265 area.extent.x += wp.x; 266 } 267 } 268 269 if (mLastHitMode & Handle_Bottom) 270 { 271 if ((area.extent.y - wp.y) >= 1) 272 { 273 area.point.y += wp.y; 274 area.extent.y -= wp.y; 275 } 276 } 277 278 if (mLastHitMode & Handle_Top) 279 { 280 if ((area.extent.y + wp.y) >= 1) 281 { 282 area.extent.y += wp.y; 283 } 284 } 285 286 setArea(area); 287 mLastMousePoint = event.mousePoint; 288} 289 290void GuiMissionAreaCtrl::onMouseEnter(const GuiEvent &) 291{ 292 mLastHitMode = Handle_None; 293 //setCursor(DefaultCursor); 294} 295 296void GuiMissionAreaCtrl::onMouseLeave(const GuiEvent &) 297{ 298 mLastHitMode = Handle_None; 299 //setCursor(DefaultCursor); 300} 301 302//------------------------------------------------------------------------------ 303 304void GuiMissionAreaCtrl::submitUndo( const UTF8 *name ) 305{ 306 // Grab the mission editor undo manager. 307 UndoManager *undoMan = NULL; 308 if ( !Sim::findObject( "EUndoManager", undoMan ) ) 309 { 310 Con::errorf( "GuiRiverEditorCtrl::submitUndo() - EUndoManager not found!" ); 311 return; 312 } 313 314 // Setup the action. 315 GuiMissionAreaUndoAction *action = new GuiMissionAreaUndoAction( name ); 316 317 action->mMissionAreaEditor = this; 318 319 action->mObjId = mMissionArea->getId(); 320 action->mArea = mMissionArea->getArea(); 321 322 undoMan->addAction( action ); 323} 324 325//------------------------------------------------------------------------------ 326 327void GuiMissionAreaCtrl::updateTerrain() 328{ 329 mTerrainBlock = getTerrainObj(); 330 updateTerrainBitmap(); 331} 332 333TerrainBlock * GuiMissionAreaCtrl::getTerrainObj() 334{ 335 SimSet * scopeAlwaysSet = Sim::getGhostAlwaysSet(); 336 for(SimSet::iterator itr = scopeAlwaysSet->begin(); itr != scopeAlwaysSet->end(); itr++) 337 { 338 TerrainBlock * terrain = dynamic_cast<TerrainBlock*>(*itr); 339 if(terrain) 340 return(terrain); 341 } 342 return(0); 343} 344 345void GuiMissionAreaCtrl::updateTerrainBitmap() 346{ 347 GBitmap * bitmap = createTerrainBitmap(); 348 if( bitmap ) 349 setBitmapHandle( GFXTexHandle( bitmap, &GFXDefaultGUIProfile, true, String("Terrain Bitmap Update") ) ); 350 else 351 setBitmap( "" ); 352} 353 354GBitmap * GuiMissionAreaCtrl::createTerrainBitmap() 355{ 356 if(!mTerrainBlock) 357 return NULL; 358 359 GBitmap * bitmap = new GBitmap(mTerrainBlock->getBlockSize(), mTerrainBlock->getBlockSize(), false, GFXFormatR8G8B8 ); 360 361 // get the min/max 362 F32 min, max; 363 mTerrainBlock->getMinMaxHeight(&min, &max); 364 365 F32 diff = max - min; 366 F32 colRange = 255.0f / diff; 367 368 // This method allocates it's bitmap above, and does all assignment 369 // in the following loop. It is not subject to 24-bit -> 32-bit conversion 370 // problems, because the texture handle creation is where the conversion would 371 // occur, if it occurs. Since the data in the texture is never read back, and 372 // the bitmap is deleted after texture-upload, this is not a problem. 373 for(S32 y = 0; y < mTerrainBlock->getBlockSize() ; y++) 374 { 375 for(S32 x = 0; x < mTerrainBlock->getBlockSize(); x++) 376 { 377 F32 height; 378 height = mTerrainBlock->getHeight(Point2I(x, y)); 379 380 U8 col = U8((height - min) * colRange); 381 ColorI color(col, col, col); 382 bitmap->setColor(x, y, color); 383 384 } 385 } 386 387 return(bitmap); 388} 389 390//------------------------------------------------------------------------------ 391 392void GuiMissionAreaCtrl::setMissionArea( MissionArea* area ) 393{ 394 mMissionArea = area; 395 if( mMissionArea ) 396 { 397 setArea(getArea()); 398 } 399} 400 401const RectI & GuiMissionAreaCtrl::getArea() 402{ 403 if( !bool(mMissionArea) ) 404 return(MissionArea::smMissionArea); 405 406 return(mMissionArea->getArea()); 407} 408 409void GuiMissionAreaCtrl::setArea(const RectI & area) 410{ 411 if( bool(mMissionArea) ) 412 { 413 mMissionArea->setArea(area); 414 mMissionArea->inspectPostApply(); 415 //onUpdate(); 416 } 417} 418 419//------------------------------------------------------------------------------ 420 421void GuiMissionAreaCtrl::drawHandle(const Point2F & pos) 422{ 423 Point2F pnt(pos.x-mHandleTextureHalfSize.x, pos.y-mHandleTextureHalfSize.y); 424 GFX->getDrawUtil()->drawBitmap(mHandleTexture, pnt); 425} 426 427void GuiMissionAreaCtrl::drawHandles(RectI & box) 428{ 429 F32 fillOffset = GFX->getFillConventionOffset(); 430 431 F32 lx = box.point.x + fillOffset, rx = box.point.x + box.extent.x + fillOffset; 432 F32 cx = (lx + rx) * 0.5f; 433 F32 by = box.point.y + fillOffset, ty = box.point.y + box.extent.y + fillOffset; 434 F32 cy = (ty + by) * 0.5f; 435 436 GFX->getDrawUtil()->clearBitmapModulation(); 437 drawHandle(Point2F(lx, ty)); 438 drawHandle(Point2F(lx, cy)); 439 drawHandle(Point2F(lx, by)); 440 drawHandle(Point2F(rx, ty)); 441 drawHandle(Point2F(rx, cy)); 442 drawHandle(Point2F(rx, by)); 443 drawHandle(Point2F(cx, ty)); 444 drawHandle(Point2F(cx, by)); 445} 446 447bool GuiMissionAreaCtrl::testWithinHandle(const Point2I & testPoint, S32 handleX, S32 handleY) 448{ 449 S32 dx = testPoint.x - handleX; 450 S32 dy = testPoint.y - handleY; 451 return dx <= Handle_Pixel_Size && dx >= -Handle_Pixel_Size && dy <= Handle_Pixel_Size && dy >= -Handle_Pixel_Size; 452} 453 454S32 GuiMissionAreaCtrl::getHitHandles(const Point2I & mousePnt, const RectI & box) 455{ 456 S32 lx = box.point.x, rx = box.point.x + box.extent.x - 1; 457 S32 cx = (lx + rx) >> 1; 458 S32 by = box.point.y, ty = box.point.y + box.extent.y - 1; 459 S32 cy = (ty + by) >> 1; 460 461 if (testWithinHandle(mousePnt, lx, ty)) 462 return Handle_Left | Handle_Top; 463 if (testWithinHandle(mousePnt, cx, ty)) 464 return Handle_Top; 465 if (testWithinHandle(mousePnt, rx, ty)) 466 return Handle_Right | Handle_Top; 467 if (testWithinHandle(mousePnt, lx, by)) 468 return Handle_Left | Handle_Bottom; 469 if (testWithinHandle(mousePnt, cx, by)) 470 return Handle_Bottom; 471 if (testWithinHandle(mousePnt, rx, by)) 472 return Handle_Right | Handle_Bottom; 473 if (testWithinHandle(mousePnt, lx, cy)) 474 return Handle_Left; 475 if (testWithinHandle(mousePnt, rx, cy)) 476 return Handle_Right; 477 if(mousePnt.x >= lx && mousePnt.x <= rx && 478 mousePnt.y >= ty && mousePnt.y <= by) 479 return(Handle_Middle); 480 481 return Handle_None; 482} 483 484//------------------------------------------------------------------------------ 485 486Point2F GuiMissionAreaCtrl::worldToScreen(const Point2F & pos) 487{ 488 return(Point2F(mCenterPos.x + (pos.x * mScale.x), mCenterPos.y + (pos.y * mScale.y))); 489} 490 491Point2I GuiMissionAreaCtrl::worldToScreen(const Point2I &pos) 492{ 493 return(Point2I(S32(mCenterPos.x + (pos.x * mScale.x)), S32(mCenterPos.y + (pos.y * mScale.y)))); 494} 495 496Point2F GuiMissionAreaCtrl::screenToWorld(const Point2F & pos) 497{ 498 return(Point2F((pos.x - mCenterPos.x) / mScale.x, (pos.y - mCenterPos.y) / mScale.y)); 499} 500 501Point2I GuiMissionAreaCtrl::screenToWorld(const Point2I &pos) 502{ 503 return(Point2I(S32((pos.x - mCenterPos.x) / mScale.x), S32((pos.y - mCenterPos.y) / mScale.y))); 504} 505 506Point2I GuiMissionAreaCtrl::screenDeltaToWorldDelta(const Point2I &screenPoint) 507{ 508 return(Point2I(S32(screenPoint.x / mScale.x), S32(screenPoint.y / mScale.y))); 509} 510 511void GuiMissionAreaCtrl::setupScreenTransform(const Point2I & offset) 512{ 513 const MatrixF & terrMat = mTerrainBlock->getTransform(); 514 Point3F terrPos; 515 terrMat.getColumn(3, &terrPos); 516 terrPos.z = 0; 517 518 F32 terrDim = mTerrainBlock->getWorldBlockSize(); 519 520 const Point2I& extenti = getExtent( ); 521 Point2F extent( static_cast<F32>( extenti.x ), static_cast<F32>( extenti.y ) ); 522 523 if(mSquareBitmap) 524 extent.x > extent.y ? extent.x = extent.y : extent.y = extent.x; 525 526 // We need to negate the y-axis so we are correctly oriented with 527 // positive y increase up the screen. 528 mScale.set(extent.x / terrDim, -extent.y / terrDim, 0); 529 530 Point3F terrOffset = -terrPos; 531 terrOffset.convolve(mScale); 532 533 // We need to add the y extent so we start from the bottom left of the control 534 // rather than the top left. 535 mCenterPos.set(terrOffset.x + F32(offset.x), terrOffset.y + F32(offset.y) + extent.y); 536} 537 538void GuiMissionAreaCtrl::getScreenMissionArea(RectI & rect) 539{ 540 RectI area = mMissionArea->getArea(); 541 Point2F pos = worldToScreen(Point2F(F32(area.point.x), F32(area.point.y))); 542 Point2F end = worldToScreen(Point2F(F32(area.point.x + area.extent.x), F32(area.point.y + area.extent.y))); 543 544 // 545 rect.point.x = S32(round_local(pos.x)); 546 rect.point.y = S32(round_local(pos.y)); 547 rect.extent.x = S32(round_local(end.x - pos.x)); 548 rect.extent.y = S32(round_local(end.y - pos.y)); 549} 550 551void GuiMissionAreaCtrl::getScreenMissionArea(RectF & rect) 552{ 553 RectI area = mMissionArea->getArea(); 554 Point2F pos = worldToScreen(Point2F(F32(area.point.x), F32(area.point.y))); 555 Point2F end = worldToScreen(Point2F(F32(area.point.x + area.extent.x), F32(area.point.y + area.extent.y))); 556 557 // 558 rect.point.x = pos.x; 559 rect.point.y = pos.y; 560 rect.extent.x = end.x - pos.x; 561 rect.extent.y = end.y - pos.y; 562} 563 564Point2I GuiMissionAreaCtrl::convertOrigin(const Point2I &pos) 565{ 566 // Convert screen point to our bottom left origin 567 Point2I pnt = globalToLocalCoord(pos); 568 const Point2I& extent = getExtent( ); 569 pnt.y = extent.y - pnt.y; 570 Point2I pt = localToGlobalCoord(pnt); 571 return pt; 572} 573 574void GuiMissionAreaCtrl::onRender(Point2I offset, const RectI & updateRect) 575{ 576 577 RectI rect(offset, getExtent()); 578 F32 fillOffset = GFX->getFillConventionOffset(); 579 580 setUpdate(); 581 582 // draw an x 583 if(!bool(mMissionArea) || !bool(mTerrainBlock)) 584 { 585 GFX->setStateBlock(mSolidStateBlock); 586 PrimBuild::color3i( 0, 0, 0 ); 587 PrimBuild::begin( GFXLineList, 4 ); 588 589 PrimBuild::vertex2f( rect.point.x + fillOffset, updateRect.point.y + fillOffset ); 590 PrimBuild::vertex2f( rect.point.x + updateRect.extent.x + fillOffset, updateRect.point.y + updateRect.extent.y + fillOffset ); 591 PrimBuild::vertex2f( rect.point.x + fillOffset, updateRect.point.y + updateRect.extent.y + fillOffset ); 592 PrimBuild::vertex2f( rect.point.x + updateRect.extent.x + fillOffset, updateRect.point.y + fillOffset ); 593 594 PrimBuild::end(); 595 596 return; 597 } 598 599 // 600 setupScreenTransform(offset); 601 602 // draw the terrain 603 if(mSquareBitmap) 604 rect.extent.x > rect.extent.y ? rect.extent.x = rect.extent.y : rect.extent.y = rect.extent.x; 605 606 GFXDrawUtil *drawer = GFX->getDrawUtil(); 607 drawer->clearBitmapModulation(); 608 drawer->drawBitmapStretch(mTextureObject, rect, GFXBitmapFlip_Y, GFXTextureFilterLinear, false); 609 610 GFX->setStateBlock(mSolidStateBlock); 611 drawer->clearBitmapModulation(); 612 613 // draw the reference axis 614 PrimBuild::begin( GFXLineList, 4 ); 615 PrimBuild::color3i( 255, 0, 0 ); 616 PrimBuild::vertex2f( rect.point.x + 5 + fillOffset, rect.point.y + rect.extent.y - 5 + fillOffset ); 617 PrimBuild::vertex2f( rect.point.x + 25 + fillOffset, rect.point.y + rect.extent.y - 5 + fillOffset ); 618 PrimBuild::color3i( 0, 255, 0 ); 619 PrimBuild::vertex2f( rect.point.x + 5 + fillOffset, rect.point.y + rect.extent.y - 5 + fillOffset ); 620 PrimBuild::vertex2f( rect.point.x + 5 + fillOffset, rect.point.y + rect.extent.y - 25 + fillOffset ); 621 PrimBuild::end(); 622 623 RectF area; 624 getScreenMissionArea(area); 625 626 // render the mission area box 627 PrimBuild::color( mMissionBoundsColor ); 628 PrimBuild::begin( GFXLineStrip, 5 ); 629 PrimBuild::vertex2f(area.point.x + fillOffset, area.point.y + fillOffset); 630 PrimBuild::vertex2f(area.point.x + area.extent.x + fillOffset, area.point.y + fillOffset); 631 PrimBuild::vertex2f(area.point.x + area.extent.x + fillOffset, area.point.y + area.extent.y + fillOffset); 632 PrimBuild::vertex2f(area.point.x + fillOffset, area.point.y + area.extent.y + fillOffset); 633 PrimBuild::vertex2f(area.point.x + fillOffset, area.point.y + fillOffset); 634 PrimBuild::end(); 635 636 // render the camera 637 //if(mRenderCamera) 638 { 639 CameraQuery camera; 640 GameProcessCameraQuery(&camera); 641 642 // farplane too far, 90' looks wrong... 643 camera.fov = mDegToRad(60.f); 644 camera.farPlane = 500.f; 645 646 // 647 F32 rot = camera.fov / 2; 648 649 // 650 VectorF ray; 651 VectorF projRayA, projRayB; 652 653 ray.set(camera.farPlane * -mSin(rot), camera.farPlane * mCos(rot), 0); 654 camera.cameraMatrix.mulV(ray, &projRayA); 655 656 ray.set(camera.farPlane * -mSin(-rot), camera.farPlane * mCos(-rot), 0); 657 camera.cameraMatrix.mulV(ray, &projRayB); 658 659 Point3F camPos; 660 camera.cameraMatrix.getColumn(3, &camPos); 661 662 Point2F s = worldToScreen(Point2F(camPos.x, camPos.y)); 663 Point2F e1 = worldToScreen(Point2F(camPos.x + projRayA.x, camPos.y + projRayA.y)); 664 Point2F e2 = worldToScreen(Point2F(camPos.x + projRayB.x, camPos.y + projRayB.y)); 665 666 PrimBuild::color( mCameraColor ); 667 PrimBuild::begin( GFXLineList, 4 ); 668 PrimBuild::vertex2f( s.x + fillOffset, s.y + fillOffset ); 669 PrimBuild::vertex2f( e1.x + fillOffset, e1.y + fillOffset ); 670 PrimBuild::vertex2f( s.x + fillOffset, s.y + fillOffset ); 671 PrimBuild::vertex2f( e2.x + fillOffset, e2.y + fillOffset ); 672 PrimBuild::end(); 673 } 674 675 // render the handles 676 RectI iArea; 677 getScreenMissionArea(iArea); 678 drawHandles(iArea); 679 680 renderChildControls(offset, updateRect); 681} 682 683//------------------------------------------------------------------------------ 684 685DefineEngineMethod( GuiMissionAreaCtrl, setMissionArea, void, ( MissionArea* area ),, 686 "@brief Set the MissionArea to edit.\n\n") 687{ 688 object->setMissionArea( area ); 689} 690 691DefineEngineMethod( GuiMissionAreaCtrl, updateTerrain, void, ( ),, 692 "@brief Update the terrain bitmap.\n\n") 693{ 694 object->updateTerrain(); 695} 696 697//------------------------------------------------------------------------------ 698 699void GuiMissionAreaUndoAction::undo() 700{ 701 MissionArea *ma = NULL; 702 if ( !Sim::findObject( mObjId, ma ) ) 703 return; 704 705 // Temporarily save the MissionArea's current data. 706 RectI area = ma->getArea(); 707 708 // Restore the MissionArea properties saved in the UndoAction 709 ma->setArea( mArea ); 710 ma->inspectPostApply(); 711 712 // Now save the previous Mission data in this UndoAction 713 // since an undo action must become a redo action and vice-versa 714 mArea = area; 715 716 // Let the script get a chance at it. 717 Con::executef( mMissionAreaEditor, "onUndo" ); 718} 719