editTSCtrl.cpp

Engine/source/gui/worldEditor/editTSCtrl.cpp

More...

Public Functions

ConsoleDocClass(EditTSCtrl , "@brief 3D view <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> used specifically by Torque 3D's <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">editors.\n\n</a>" "For Torque 3D editors only, not <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> actual game <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">development\n\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Editors\n</a>" " @internal" )
DefineEngineMethod(EditTSCtrl , getDisplayType , S32 , () , "" )
DefineEngineMethod(EditTSCtrl , getGizmo , S32 , () , "" )
DefineEngineMethod(EditTSCtrl , getOrthoFOV , F32 , () , "Return the FOV <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> orthographic views." )
DefineEngineMethod(EditTSCtrl , isMiddleMouseDown , bool , () , "" )
DefineEngineMethod(EditTSCtrl , renderBox , void , (Point3F pos, Point3F size) , "" )
DefineEngineMethod(EditTSCtrl , renderCircle , void , (Point3F pos, Point3F normal, F32 radius, S32 segments) , (0) , "" )
DefineEngineMethod(EditTSCtrl , renderLine , void , (Point3F start, Point3F end, F32 lineWidth) , (0) , "" )
DefineEngineMethod(EditTSCtrl , renderSphere , void , (Point3F pos, F32 radius, S32 sphereLevel) , (0) , "" )
DefineEngineMethod(EditTSCtrl , renderTriangle , void , (Point3F a, Point3F b, Point3F c) , "" )
DefineEngineMethod(EditTSCtrl , setDisplayType , void , (S32 displayType) , "" )
DefineEngineMethod(EditTSCtrl , setOrthoFOV , void , (F32 fov) , "Set the FOV <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> orthographic views." )

Detailed Description

Public Functions

ConsoleDocClass(EditTSCtrl , "@brief 3D view <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> used specifically by Torque 3D's <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">editors.\n\n</a>" "For Torque 3D editors only, not <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> actual game <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">development\n\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Editors\n</a>" " @internal" )

DefineEngineMethod(EditTSCtrl , getDisplayType , S32 , () , "" )

DefineEngineMethod(EditTSCtrl , getGizmo , S32 , () , "" )

DefineEngineMethod(EditTSCtrl , getOrthoFOV , F32 , () , "Return the FOV <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> orthographic views." )

DefineEngineMethod(EditTSCtrl , isMiddleMouseDown , bool , () , "" )

DefineEngineMethod(EditTSCtrl , renderBox , void , (Point3F pos, Point3F size) , "" )

DefineEngineMethod(EditTSCtrl , renderCircle , void , (Point3F pos, Point3F normal, F32 radius, S32 segments) , (0) , "" )

DefineEngineMethod(EditTSCtrl , renderLine , void , (Point3F start, Point3F end, F32 lineWidth) , (0) , "" )

DefineEngineMethod(EditTSCtrl , renderSphere , void , (Point3F pos, F32 radius, S32 sphereLevel) , (0) , "" )

DefineEngineMethod(EditTSCtrl , renderTriangle , void , (Point3F a, Point3F b, Point3F c) , "" )

DefineEngineMethod(EditTSCtrl , setDisplayType , void , (S32 displayType) , "" )

DefineEngineMethod(EditTSCtrl , setOrthoFOV , void , (F32 fov) , "Set the FOV <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> orthographic views." )

IMPLEMENT_CONOBJECT(EditTSCtrl )

sceneBoundsCalcCallback(SceneObject * obj, void * key)

   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 "platform/platform.h"
  25#include "gui/worldEditor/editTSCtrl.h"
  26
  27#include "console/consoleTypes.h"
  28#include "console/engineAPI.h"
  29#include "T3D/gameBase/gameConnection.h"
  30#include "gui/worldEditor/editor.h"
  31#include "gui/core/guiCanvas.h"
  32#include "terrain/terrData.h"
  33#include "T3D/missionArea.h"
  34#include "gfx/primBuilder.h"
  35#include "gfx/gfxDrawUtil.h"
  36#include "gfx/gfxTransformSaver.h"
  37#include "gfx/gfxDebugEvent.h"
  38#include "scene/sceneManager.h"
  39#include "scene/sceneRenderState.h"
  40#include "renderInstance/renderBinManager.h"
  41
  42#include "T3D/Scene.h"
  43
  44IMPLEMENT_CONOBJECT(EditTSCtrl);
  45ConsoleDocClass( EditTSCtrl,
  46   "@brief 3D view control used specifically by Torque 3D's editors.\n\n"
  47
  48   "For Torque 3D editors only, not for actual game development\n\n"
  49
  50   "@ingroup Editors\n"
  51
  52   "@internal"
  53);
  54
  55Point3F  EditTSCtrl::smCamPos;
  56MatrixF  EditTSCtrl::smCamMatrix;
  57bool     EditTSCtrl::smCamOrtho = false;
  58F32      EditTSCtrl::smCamNearPlane;
  59F32      EditTSCtrl::smCamFOV = 75.0f;
  60F32      EditTSCtrl::smVisibleDistanceScale = 1.0f;
  61U32      EditTSCtrl::smSceneBoundsMask = EnvironmentObjectType | TerrainObjectType | WaterObjectType | CameraObjectType;
  62Point3F  EditTSCtrl::smMinSceneBounds = Point3F(500.0f, 500.0f, 500.0f);
  63
  64EditTSCtrl::EditTSCtrl()
  65{
  66   mGizmoProfile = NULL;
  67   mGizmo = NULL;
  68
  69   mRenderMissionArea = true;
  70   mMissionAreaFillColor.set(255,0,0,20);
  71   mMissionAreaFrameColor.set(255,0,0,128);
  72   mMissionAreaHeightAdjust = 5.0f;
  73
  74   mConsoleFrameColor.set(255,0,0,255);
  75   mConsoleFillColor.set(255,0,0,120);
  76   mConsoleSphereLevel = 1;
  77   mConsoleCircleSegments = 32;
  78   mConsoleLineWidth = 1;
  79   mRightMousePassThru = true;
  80   mMiddleMousePassThru = true;
  81
  82   mConsoleRendering = false;
  83
  84   mDisplayType = DisplayTypePerspective;
  85   mOrthoFOV = 50.0f;
  86   mOrthoCamTrans.set(0.0f, 0.0f, 0.0f);
  87
  88   mIsoCamAngle = mDegToRad(45.0f);
  89   mIsoCamRot = EulerF(0, 0, 0);
  90
  91   mRenderGridPlane = true;
  92   mGridPlaneOriginColor = ColorI(255, 255, 255, 100);
  93   mGridPlaneColor = ColorI(102, 102, 102, 100);
  94   mGridPlaneMinorTickColor = ColorI(51, 51, 51, 100);
  95   mGridPlaneMinorTicks = 9;
  96   mGridPlaneSize = 1.0f;
  97   mGridPlaneSizePixelBias = 10.0f;
  98
  99   mLastMousePos.set(0, 0);
 100
 101   mAllowBorderMove = false;
 102   mMouseMoveBorder = 20;
 103   mMouseMoveSpeed = 0.1f;
 104   mLastBorderMoveTime = 0;
 105   mLeftMouseDown = false;
 106   mRightMouseDown = false;
 107   mMiddleMouseDown = false;
 108   mMiddleMouseTriggered = false;
 109   mMouseLeft = false;
 110   mLastMouseClamping = false;
 111   mBlendSB = NULL;
 112
 113}
 114
 115EditTSCtrl::~EditTSCtrl()
 116{
 117   mBlendSB = NULL;
 118}
 119
 120//------------------------------------------------------------------------------
 121
 122bool EditTSCtrl::onAdd()
 123{
 124   if(!Parent::onAdd())
 125      return(false);
 126
 127   // give all derived access to the fields
 128   setModStaticFields(true);
 129
 130   GFXStateBlockDesc blenddesc;
 131   blenddesc.setBlend(true, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha);
 132   mBlendSB = GFX->createStateBlock( blenddesc );
 133
 134   if ( !mGizmoProfile )
 135   {
 136      Con::errorf( "EditTSCtrl::onadd - gizmoProfile was not assigned, cannot create control!" );
 137      return false;
 138   }
 139
 140   mGizmo = new Gizmo();
 141   mGizmo->setProfile( mGizmoProfile );
 142   mGizmo->registerObject();
 143
 144   return true;
 145}
 146
 147void EditTSCtrl::onRemove()
 148{
 149   Parent::onRemove();
 150
 151   if ( mGizmo )
 152      mGizmo->deleteObject();
 153}
 154
 155void EditTSCtrl::onRender(Point2I offset, const RectI &updateRect)
 156{
 157   // Perform possible mouse border move...
 158   if(mAllowBorderMove && smCamOrtho && !mLeftMouseDown && !mRightMouseDown && !mMouseLeft)
 159   {
 160      Point2I ext = getExtent();
 161
 162      U32 current = Platform::getRealMilliseconds();
 163      bool update = false;
 164      F32 movex = 0.0f;
 165      F32 movey = 0.0f;
 166
 167      Point2I localMouse = globalToLocalCoord(mLastMousePos);
 168
 169      if(localMouse.x <= mMouseMoveBorder || localMouse.x >= ext.x - mMouseMoveBorder)
 170      {
 171         if(mLastBorderMoveTime != 0)
 172         {
 173            U32 dt = current - mLastBorderMoveTime;
 174            if(localMouse.x <= mMouseMoveBorder)
 175            {
 176               movex = mMouseMoveSpeed * dt;
 177            }
 178            else
 179            {
 180               movex = -mMouseMoveSpeed * dt;
 181            }
 182         }
 183         update = true;
 184      }
 185
 186      if(localMouse.y <= mMouseMoveBorder || localMouse.y >= ext.y - mMouseMoveBorder)
 187      {
 188         if(mLastBorderMoveTime != 0)
 189         {
 190            U32 dt = current - mLastBorderMoveTime;
 191            if(localMouse.y <= mMouseMoveBorder)
 192            {
 193               movey = mMouseMoveSpeed * dt;
 194            }
 195            else
 196            {
 197               movey = -mMouseMoveSpeed * dt;
 198            }
 199         }
 200         update = true;
 201      }
 202
 203      if(update)
 204      {
 205         mLastBorderMoveTime = current;
 206         calcOrthoCamOffset(movex, movey);
 207      }
 208      else
 209      {
 210         mLastBorderMoveTime = 0;
 211      }
 212   }
 213
 214   updateGuiInfo();
 215   Parent::onRender(offset, updateRect);
 216
 217}
 218
 219//------------------------------------------------------------------------------
 220
 221void EditTSCtrl::initPersistFields()
 222{
 223   addGroup( "Grid" );
 224   
 225      addField( "gridSize", TypeF32, Offset( mGridPlaneSize, EditTSCtrl ) );
 226      addField( "gridColor", TypeColorI, Offset( mGridPlaneColor, EditTSCtrl ) );
 227      addField( "gridOriginColor", TypeColorI, Offset( mGridPlaneOriginColor, EditTSCtrl ) );
 228      addField( "gridMinorTickColor", TypeColorI, Offset( mGridPlaneMinorTickColor, EditTSCtrl ) );
 229      addField( "renderOrthoGrid", TypeBool, Offset( mRenderGridPlane, EditTSCtrl ),
 230         "Whether to render the grid in orthographic axial projections." );
 231      addField( "renderOrthoGridPixelBias", TypeF32, Offset( mGridPlaneSizePixelBias, EditTSCtrl ),
 232         "Grid patch pixel size below which to switch to coarser grid resolutions." );
 233   
 234   endGroup( "Grid" );
 235   
 236   addGroup("Mission Area");  
 237   
 238      addField("renderMissionArea", TypeBool, Offset(mRenderMissionArea, EditTSCtrl));
 239      addField("missionAreaFillColor", TypeColorI, Offset(mMissionAreaFillColor, EditTSCtrl));
 240      addField("missionAreaFrameColor", TypeColorI, Offset(mMissionAreaFrameColor, EditTSCtrl));
 241      addField("missionAreaHeightAdjust", TypeF32, Offset(mMissionAreaHeightAdjust, EditTSCtrl),
 242         "How high above and below the terrain to render the mission area bounds." );
 243      
 244   endGroup("Mission Area");  
 245
 246   addGroup("BorderMovement");   
 247   
 248      addField("allowBorderMove", TypeBool, Offset(mAllowBorderMove, EditTSCtrl));
 249      addField("borderMovePixelSize", TypeS32, Offset(mMouseMoveBorder, EditTSCtrl));
 250      addField("borderMoveSpeed", TypeF32, Offset(mMouseMoveSpeed, EditTSCtrl));
 251      
 252   endGroup("BorderMovement");   
 253
 254   addGroup("Misc"); 
 255   
 256      addField("consoleFrameColor", TypeColorI, Offset(mConsoleFrameColor, EditTSCtrl));
 257      addField("consoleFillColor", TypeColorI, Offset(mConsoleFillColor, EditTSCtrl));
 258      addField("consoleSphereLevel", TypeS32, Offset(mConsoleSphereLevel, EditTSCtrl));
 259      addField("consoleCircleSegments", TypeS32, Offset(mConsoleCircleSegments, EditTSCtrl));
 260      addField("consoleLineWidth", TypeS32, Offset(mConsoleLineWidth, EditTSCtrl));
 261      addField("gizmoProfile", TYPEID< GizmoProfile >(), Offset(mGizmoProfile, EditTSCtrl));
 262      
 263   endGroup("Misc");
 264   
 265   Parent::initPersistFields();
 266}
 267
 268void EditTSCtrl::consoleInit()
 269{
 270   Con::addVariable("pref::WorldEditor::visibleDistanceScale", TypeF32, &EditTSCtrl::smVisibleDistanceScale, "Scale factor for the visible render distance.\n"
 271      "@ingroup ");
 272   
 273   Con::addVariable("pref::WorldEditor::cameraFOV", TypeF32, &EditTSCtrl::smCamFOV, "Field of view for editor's perspective camera, in degrees.\n"
 274      "@ingroup ");
 275   
 276   Con::setIntVariable( "$EditTsCtrl::DisplayTypeTop", DisplayTypeTop);
 277   Con::setIntVariable( "$EditTsCtrl::DisplayTypeBottom", DisplayTypeBottom);
 278   Con::setIntVariable( "$EditTsCtrl::DisplayTypeFront", DisplayTypeFront);
 279   Con::setIntVariable( "$EditTsCtrl::DisplayTypeBack", DisplayTypeBack);
 280   Con::setIntVariable( "$EditTsCtrl::DisplayTypeLeft", DisplayTypeLeft);
 281   Con::setIntVariable( "$EditTsCtrl::DisplayTypeRight", DisplayTypeRight);
 282   Con::setIntVariable( "$EditTsCtrl::DisplayTypePerspective", DisplayTypePerspective);
 283   Con::setIntVariable( "$EditTsCtrl::DisplayTypeIsometric", DisplayTypeIsometric);
 284}
 285
 286//------------------------------------------------------------------------------
 287
 288bool EditTSCtrl::resize(const Point2I& newPosition, const Point2I& newExtent)
 289{
 290   if (!Parent::resize(newPosition, newExtent))
 291      return false;
 292
 293   // Notify the scripts
 294   if (isMethod("onResize"))
 295      Con::executef(this, "onResize", newPosition, newExtent);
 296
 297   return true;
 298}
 299//------------------------------------------------------------------------------
 300void EditTSCtrl::make3DMouseEvent(Gui3DMouseEvent & gui3DMouseEvent, const GuiEvent & event)
 301{
 302   (GuiEvent&)(gui3DMouseEvent) = event;
 303   gui3DMouseEvent.mousePoint = event.mousePoint;
 304
 305   if(!smCamOrtho)
 306   {
 307      // get the eye pos and the mouse vec from that...
 308      Point3F screenPoint((F32)gui3DMouseEvent.mousePoint.x, (F32)gui3DMouseEvent.mousePoint.y, 1.0f);
 309
 310      Point3F wp;
 311      unproject(screenPoint, &wp);
 312
 313      gui3DMouseEvent.pos = smCamPos;
 314      gui3DMouseEvent.vec = wp - smCamPos;
 315      gui3DMouseEvent.vec.normalizeSafe();
 316   }
 317   else
 318   {
 319      // get the eye pos and the mouse vec from that...
 320      Point3F screenPoint((F32)gui3DMouseEvent.mousePoint.x, (F32)gui3DMouseEvent.mousePoint.y, 0.0f);
 321
 322      Point3F np, fp;
 323      unproject(screenPoint, &np);
 324
 325      gui3DMouseEvent.pos = np;
 326      smCamMatrix.getColumn( 1, &(gui3DMouseEvent.vec) );
 327   }
 328}
 329
 330//------------------------------------------------------------------------------
 331
 332TerrainBlock* EditTSCtrl::getActiveTerrain()
 333{
 334   // Find a terrain block
 335   SimSet* scopeAlwaysSet = Sim::getGhostAlwaysSet();
 336   for(SimSet::iterator itr = scopeAlwaysSet->begin(); itr != scopeAlwaysSet->end(); itr++)
 337   {
 338      TerrainBlock* block = dynamic_cast<TerrainBlock*>(*itr);
 339      if( block )
 340         return block;
 341   }
 342
 343   return NULL;
 344}
 345
 346//------------------------------------------------------------------------------
 347
 348void EditTSCtrl::setDisplayType( S32 type )
 349{
 350   mDisplayType = type;
 351   
 352   // Disable middle-mouse pass-thru in ortho views so we can
 353   // use the middle mouse button for navigation.
 354
 355   mMiddleMousePassThru = !isOrthoDisplayType();
 356   
 357   if( mGizmo )
 358   {
 359      // Disable gizmo's grid plane in the isometric views since
 360      // they will render with the grid from EditTSCtrl.  Also disable
 361      // the move grid as it doesn't make sense in ortho views.
 362      
 363      if( type != DisplayTypePerspective )
 364      {
 365         mGizmo->setGridPlaneEnabled( false );
 366         mGizmo->setMoveGridEnabled( false );
 367      }
 368      else
 369      {
 370         mGizmo->setGridPlaneEnabled( true );
 371         mGizmo->setMoveGridEnabled( true );
 372      }
 373   }
 374}
 375
 376//------------------------------------------------------------------------------
 377
 378void EditTSCtrl::getCursor(GuiCursor *&cursor, bool &visible, const GuiEvent &event)
 379{
 380   make3DMouseEvent(mLastEvent, event);
 381   get3DCursor(cursor, visible, mLastEvent);
 382}
 383
 384void EditTSCtrl::get3DCursor(GuiCursor *&cursor, bool &visible, const Gui3DMouseEvent &event)
 385{
 386   TORQUE_UNUSED(event);
 387   cursor = NULL;
 388   visible = false;
 389}
 390
 391void EditTSCtrl::onMouseUp(const GuiEvent & event)
 392{
 393   mLeftMouseDown = false;
 394   make3DMouseEvent(mLastEvent, event);
 395   on3DMouseUp(mLastEvent);
 396}
 397
 398void EditTSCtrl::onMouseDown(const GuiEvent & event)
 399{
 400   mLeftMouseDown = true;
 401   mLastBorderMoveTime = 0;
 402   make3DMouseEvent(mLastEvent, event);
 403   on3DMouseDown(mLastEvent);
 404   
 405   setFirstResponder();
 406}
 407
 408void EditTSCtrl::onMouseMove(const GuiEvent & event)
 409{
 410   make3DMouseEvent(mLastEvent, event);
 411   on3DMouseMove(mLastEvent);
 412
 413   mLastMousePos = event.mousePoint;
 414}
 415
 416void EditTSCtrl::onMouseDragged(const GuiEvent & event)
 417{
 418   make3DMouseEvent(mLastEvent, event);
 419   on3DMouseDragged(mLastEvent);
 420}
 421
 422void EditTSCtrl::onMouseEnter(const GuiEvent & event)
 423{
 424   mMouseLeft = false;
 425   make3DMouseEvent(mLastEvent, event);
 426   on3DMouseEnter(mLastEvent);
 427}
 428
 429void EditTSCtrl::onMouseLeave(const GuiEvent & event)
 430{
 431   mMouseLeft = true;
 432   mLastBorderMoveTime = 0;
 433   make3DMouseEvent(mLastEvent, event);
 434   on3DMouseLeave(mLastEvent);
 435}
 436
 437void EditTSCtrl::onRightMouseDown(const GuiEvent & event)
 438{
 439   // always process the right mouse event first...
 440
 441   mRightMouseDown = true;
 442   mLastBorderMoveTime = 0;
 443
 444   make3DMouseEvent(mLastEvent, event);
 445   on3DRightMouseDown(mLastEvent);
 446
 447   if(!mLeftMouseDown && mRightMousePassThru && mProfile->mCanKeyFocus)
 448   {
 449      GuiCanvas *pCanvas = getRoot();
 450      if( !pCanvas )
 451         return;
 452
 453      PlatformWindow *pWindow = static_cast<GuiCanvas*>(getRoot())->getPlatformWindow();
 454      if( !pWindow )
 455         return;
 456
 457      PlatformCursorController *pController = pWindow->getCursorController();
 458      if( !pController )
 459         return;
 460
 461      // ok, gotta disable the mouse
 462      // script functions are lockMouse(true); Canvas.cursorOff();
 463      pWindow->setMouseLocked(true);
 464      pCanvas->setCursorON( false );
 465
 466      if(mDisplayType != DisplayTypePerspective)
 467      {
 468         mouseLock();
 469         mLastMousePos = event.mousePoint;
 470         pCanvas->setForceMouseToGUI(true);
 471         mLastMouseClamping = pCanvas->getClampTorqueCursor();
 472         pCanvas->setClampTorqueCursor(false);
 473      }
 474
 475      if(mDisplayType == DisplayTypeIsometric)
 476      {
 477         // Store the screen center point on the terrain for a possible rotation
 478         TerrainBlock* activeTerrain = getActiveTerrain();
 479         if( activeTerrain )
 480         {
 481            F32 extx, exty;
 482            if(event.modifier & SI_SHIFT)
 483            {
 484               extx = F32(event.mousePoint.x);
 485               exty = F32(event.mousePoint.y);
 486            }
 487            else
 488            {
 489               extx = getExtent().x * 0.5;
 490               exty = getExtent().y * 0.5;
 491            }
 492            Point3F sp(extx, exty, 0.0f); // Near plane projection
 493            Point3F start;
 494            unproject(sp, &start);
 495
 496            Point3F end = start + mLastEvent.vec * 4000.0f;
 497            Point3F tStartPnt, tEndPnt;
 498            activeTerrain->getTransform().mulP(start, &tStartPnt);
 499            activeTerrain->getTransform().mulP(end, &tEndPnt);
 500
 501            RayInfo info;
 502            bool result = activeTerrain->castRay(tStartPnt, tEndPnt, &info);
 503            if(result)
 504            {
 505               info.point.interpolate(start, end, info.t);
 506               mIsoCamRotCenter = info.point;
 507            }
 508            else
 509            {
 510               mIsoCamRotCenter = start;
 511            }
 512         }
 513         else
 514         {
 515            F32 extx = getExtent().x * 0.5;
 516            F32 exty = getExtent().y * 0.5;
 517            Point3F sp(extx, exty, 0.0f); // Near plane projection
 518            unproject(sp, &mIsoCamRotCenter);
 519         }
 520      }
 521
 522      setFirstResponder();
 523   }
 524}
 525
 526void EditTSCtrl::onRightMouseUp(const GuiEvent & event)
 527{
 528   mRightMouseDown = false;
 529   make3DMouseEvent(mLastEvent, event);
 530   on3DRightMouseUp(mLastEvent);
 531}
 532
 533void EditTSCtrl::onRightMouseDragged(const GuiEvent & event)
 534{
 535   make3DMouseEvent(mLastEvent, event);
 536   on3DRightMouseDragged(mLastEvent);
 537
 538   // Handle zoom of orthographic views.
 539   
 540   if( isOrthoDisplayType() )
 541   {
 542      orthoZoom( ( event.mousePoint.y - mLastMousePos.y ) * 0.5f );
 543      mLastMousePos = event.mousePoint;
 544   }
 545}
 546
 547void EditTSCtrl::onMiddleMouseDown(const GuiEvent & event)
 548{
 549   mMiddleMouseDown = true;
 550   mMiddleMouseTriggered = false;
 551   mLastBorderMoveTime = 0;
 552
 553   if(!mLeftMouseDown && !mRightMouseDown && mMiddleMousePassThru && mProfile->mCanKeyFocus)
 554   {
 555      GuiCanvas *pCanvas = getRoot();
 556      if( !pCanvas )
 557         return;
 558
 559      PlatformWindow *pWindow = static_cast<GuiCanvas*>(getRoot())->getPlatformWindow();
 560      if( !pWindow )
 561         return;
 562
 563      PlatformCursorController *pController = pWindow->getCursorController();
 564      if( !pController )
 565         return;
 566
 567      // ok, gotta disable the mouse
 568      // script functions are lockMouse(true); Canvas.cursorOff();
 569      pWindow->setMouseLocked(true);
 570      pCanvas->setCursorON( false );
 571
 572      // Trigger 2 is used by the camera
 573      MoveManager::mTriggerCount[2]++;
 574      mMiddleMouseTriggered = true;
 575
 576      setFirstResponder();
 577   }
 578}
 579
 580void EditTSCtrl::onMiddleMouseUp(const GuiEvent & event)
 581{
 582   // Trigger 2 is used by the camera
 583   if( mMiddleMouseTriggered )
 584   {
 585      MoveManager::mTriggerCount[2]++;
 586      mMiddleMouseTriggered = false;
 587   }
 588
 589   mMiddleMouseDown = false;
 590}
 591
 592void EditTSCtrl::onMiddleMouseDragged(const GuiEvent & event)
 593{
 594   // Handle translation of orthographic views.
 595   
 596   if( isOrthoDisplayType() )
 597   {
 598      calcOrthoCamOffset((event.mousePoint.x - mLastMousePos.x), (event.mousePoint.y - mLastMousePos.y), event.modifier);
 599      mLastMousePos = event.mousePoint;
 600   }
 601}
 602
 603bool EditTSCtrl::onMouseWheelUp( const GuiEvent &event )
 604{
 605   // Looks like this should be zooming based on a factor of the GuiEvent.fval
 606   if( isOrthoDisplayType() && !event.modifier )
 607   {
 608      orthoZoom( -2.f );
 609      return true;
 610   }
 611
 612   make3DMouseEvent(mLastEvent, event);
 613   on3DMouseWheelUp(mLastEvent);
 614
 615   return false;
 616}
 617
 618bool EditTSCtrl::onMouseWheelDown( const GuiEvent &event )
 619{
 620   // Looks like this should be zooming based on a factor of the GuiEvent.fval
 621   if(mDisplayType != DisplayTypePerspective && !event.modifier)
 622   {
 623      orthoZoom( 2.f );
 624      return true;
 625   }
 626
 627   make3DMouseEvent(mLastEvent, event);
 628   on3DMouseWheelDown(mLastEvent);
 629
 630   return false;
 631}
 632
 633
 634bool EditTSCtrl::onInputEvent(const InputEventInfo & event)
 635{
 636
 637   if(mRightMousePassThru && event.deviceType == MouseDeviceType &&
 638      event.objInst == KEY_BUTTON1 && event.action == SI_BREAK)
 639   {
 640      // if the right mouse pass thru is enabled,
 641      // we want to reactivate mouse on a right mouse button up
 642      GuiCanvas *pCanvas = getRoot();
 643      if( !pCanvas )
 644         return false;
 645
 646      PlatformWindow *pWindow = static_cast<GuiCanvas*>(getRoot())->getPlatformWindow();
 647      if( !pWindow )
 648         return false;
 649
 650      PlatformCursorController *pController = pWindow->getCursorController();
 651      if( !pController )
 652         return false;
 653
 654      pWindow->setMouseLocked(false);
 655      pCanvas->setCursorON( true );
 656
 657      if(mDisplayType != DisplayTypePerspective)
 658      {
 659         mouseUnlock();
 660         pCanvas->setForceMouseToGUI(false);
 661         pCanvas->setClampTorqueCursor(mLastMouseClamping);
 662      }
 663   }
 664
 665   if(mMiddleMousePassThru && event.deviceType == MouseDeviceType &&
 666      event.objInst == KEY_BUTTON2 && event.action == SI_BREAK)
 667   {
 668      // if the middle mouse pass thru is enabled,
 669      // we want to reactivate mouse on a middle mouse button up
 670      GuiCanvas *pCanvas = getRoot();
 671      if( !pCanvas )
 672         return false;
 673
 674      PlatformWindow *pWindow = static_cast<GuiCanvas*>(getRoot())->getPlatformWindow();
 675      if( !pWindow )
 676         return false;
 677
 678      PlatformCursorController *pController = pWindow->getCursorController();
 679      if( !pController )
 680         return false;
 681
 682      pWindow->setMouseLocked(false);
 683      pCanvas->setCursorON( true );
 684   }
 685
 686   // we return false so that the canvas can properly process the right mouse button up...
 687   return false;
 688}
 689
 690//------------------------------------------------------------------------------
 691
 692void EditTSCtrl::orthoZoom( F32 steps )
 693{
 694   //TODO: this really should be proportional
 695   
 696   mOrthoFOV += steps;
 697
 698   if( mOrthoFOV < 1.0f )
 699      mOrthoFOV = 1.0f;
 700}
 701
 702void EditTSCtrl::calcOrthoCamOffset(F32 mousex, F32 mousey, U8 modifier)
 703{
 704   F32 camScale = 0.01f;
 705
 706   switch(mDisplayType)
 707   {
 708      case DisplayTypeTop:
 709         mOrthoCamTrans.x -= mousex * mOrthoFOV * camScale;
 710         mOrthoCamTrans.y += mousey * mOrthoFOV * camScale;
 711         break;
 712
 713      case DisplayTypeBottom:
 714         mOrthoCamTrans.x -= mousex * mOrthoFOV * camScale;
 715         mOrthoCamTrans.y -= mousey * mOrthoFOV * camScale;
 716         break;
 717
 718      case DisplayTypeFront:
 719         mOrthoCamTrans.x -= mousex * mOrthoFOV * camScale;
 720         mOrthoCamTrans.z += mousey * mOrthoFOV * camScale;
 721         break;
 722
 723      case DisplayTypeBack:
 724         mOrthoCamTrans.x += mousex * mOrthoFOV * camScale;
 725         mOrthoCamTrans.z += mousey * mOrthoFOV * camScale;
 726         break;
 727
 728      case DisplayTypeLeft:
 729         mOrthoCamTrans.y += mousex * mOrthoFOV * camScale;
 730         mOrthoCamTrans.z += mousey * mOrthoFOV * camScale;
 731         break;
 732
 733      case DisplayTypeRight:
 734         mOrthoCamTrans.y -= mousex * mOrthoFOV * camScale;
 735         mOrthoCamTrans.z += mousey * mOrthoFOV * camScale;
 736         break;
 737
 738      case DisplayTypeIsometric:
 739         if(modifier & SI_PRIMARY_CTRL)
 740         {
 741            // NOTE: Maybe move the center of rotation code to right mouse down to avoid compound errors?
 742            F32 rot = mDegToRad(mousex);
 743
 744            Point3F campos = (mRawCamPos + mOrthoCamTrans) - mIsoCamRotCenter;
 745            MatrixF mat(EulerF(0, 0, rot));
 746            mat.mulP(campos);
 747            mOrthoCamTrans = (campos + mIsoCamRotCenter) - mRawCamPos;
 748            mIsoCamRot.z += rot;
 749
 750         }
 751         else
 752         {
 753            mOrthoCamTrans.x -= mousex * mOrthoFOV * camScale * mCos(mIsoCamRot.z) - mousey * mOrthoFOV * camScale * mSin(mIsoCamRot.z);
 754            mOrthoCamTrans.y += mousex * mOrthoFOV * camScale * mSin(mIsoCamRot.z) + mousey * mOrthoFOV * camScale * mCos(mIsoCamRot.z);
 755         }
 756         break;
 757   }
 758}
 759
 760void EditTSCtrl::updateGizmo()
 761{
 762   mGizmoProfile->restoreDefaultState();
 763}
 764
 765//------------------------------------------------------------------------------
 766
 767void EditTSCtrl::renderWorld(const RectI & updateRect)
 768{
 769   // Make sure that whatever the editor does, it doesn't
 770   // dirty the GFX transform state.
 771   GFXTransformSaver saver;
 772
 773   updateGizmo();
 774
 775   gClientSceneGraph->setDisplayTargetResolution(getExtent());
 776
 777   // Use a render instance to do editor 3D scene 
 778   // rendering after HDR is processed and while the depth 
 779   // buffer is still intact.
 780   RenderPassManager *rpm = gClientSceneGraph->getDefaultRenderPass();
 781   ObjectRenderInst *inst = rpm->allocInst<ObjectRenderInst>();
 782   inst->type = RenderPassManager::RIT_Editor;
 783   inst->renderDelegate.bind(this, &EditTSCtrl::_renderScene);
 784   rpm->addInst(inst);
 785
 786   if( mDisplayType == DisplayTypePerspective )
 787      gClientSceneGraph->renderScene( SPT_Diffuse );
 788   else
 789   {
 790      // If we are in an orthographic mode, do a special render
 791      // with AL, fog, and PostFX disabled.
 792
 793      FogData savedFogData = gClientSceneGraph->getFogData();
 794      gClientSceneGraph->setFogData( FogData() );
 795
 796      SceneRenderState renderState
 797      (
 798         gClientSceneGraph,
 799         SPT_Diffuse
 800      );
 801
 802      gClientSceneGraph->renderScene( &renderState );
 803      gClientSceneGraph->setFogData( savedFogData );
 804   }
 805}
 806
 807void EditTSCtrl::_renderScene( ObjectRenderInst*, SceneRenderState *state, BaseMatInstance* )
 808{
 809   GFXTransformSaver saver;
 810
 811   // render through console callbacks
 812   Scene* scene = Scene::getRootScene();
 813   if(scene)
 814   {
 815      mConsoleRendering = true;
 816
 817      // [ rene, 27-Jan-10 ] This calls onEditorRender on the server objects instead
 818      //    of on the client objects which seems a bit questionable to me.
 819 
 820      for(SimSetIterator itr(scene); *itr; ++itr)
 821      {
 822         SceneObject* object = dynamic_cast< SceneObject* >( *itr );
 823         if( object && object->isRenderEnabled() && !object->isHidden() )
 824         {
 825            char buf[2][16];
 826            dSprintf(buf[0], 16, object->isSelected() ? "true" : "false");
 827            dSprintf(buf[1], 16, object->isExpanded() ? "true" : "false");
 828            
 829            Con::executef( object, "onEditorRender", getIdString(), buf[0], buf[1] );
 830         }
 831      }
 832
 833      mConsoleRendering = false;
 834   }
 835
 836   // render the mission area...
 837   renderMissionArea();
 838
 839   // Draw the grid
 840   if ( mRenderGridPlane )
 841      renderGrid();
 842
 843   // render the editor stuff
 844   renderScene(mSaveViewport);
 845
 846   // Draw the camera axis
 847   GFX->setClipRect(mSaveViewport);
 848   GFX->setStateBlock(mDefaultGuiSB);
 849   renderCameraAxis();
 850}
 851
 852void EditTSCtrl::renderMissionArea()
 853{
 854   MissionArea* obj = MissionArea::getServerObject();
 855   if ( !obj )
 856      return;
 857
 858   if ( !mRenderMissionArea && !obj->isSelected() )
 859      return;
 860
 861   GFXDEBUGEVENT_SCOPE( Editor_renderMissionArea, ColorI::WHITE );
 862
 863   F32 minHeight = 0.0f;
 864   F32 maxHeight = 0.0f;
 865
 866   TerrainBlock* terrain = getActiveTerrain();
 867   if ( terrain )
 868   {
 869      terrain->getMinMaxHeight( &minHeight, &maxHeight );
 870      Point3F pos = terrain->getPosition();
 871
 872      maxHeight += pos.z + mMissionAreaHeightAdjust;
 873      minHeight += pos.z - mMissionAreaHeightAdjust;
 874   }
 875
 876   const RectI& area = obj->getArea();
 877   Box3F areaBox( area.point.x,
 878                  area.point.y,
 879                  minHeight,
 880                  area.point.x + area.extent.x,
 881                  area.point.y + area.extent.y,
 882                  maxHeight );
 883
 884   GFXDrawUtil* drawer = GFX->getDrawUtil();
 885
 886   GFXStateBlockDesc desc;
 887   desc.setCullMode( GFXCullNone );
 888   desc.setBlend( true );
 889   desc.setZReadWrite( false, false );
 890
 891   desc.setFillModeSolid();
 892   drawer->drawCube( desc, areaBox, mMissionAreaFillColor );
 893
 894   desc.setFillModeWireframe();
 895   drawer->drawCube( desc, areaBox, mMissionAreaFrameColor );
 896}
 897
 898void EditTSCtrl::renderCameraAxis()
 899{
 900   GFXDEBUGEVENT_SCOPE( Editor_renderCameraAxis, ColorI::WHITE );
 901
 902   static MatrixF sRotMat(EulerF( (M_PI_F / -2.0f), 0.0f, 0.0f));
 903
 904   MatrixF camMat = mLastCameraQuery.cameraMatrix;
 905   camMat.mul(sRotMat);
 906   camMat.inverse();
 907
 908   MatrixF axis;
 909   axis.setColumn(0, Point3F(1, 0, 0));
 910   axis.setColumn(1, Point3F(0, 0, 1));
 911   axis.setColumn(2, Point3F(0, -1, 0));
 912   axis.mul(camMat);
 913
 914   Point3F forwardVec, upVec, rightVec;
 915   axis.getColumn( 2, &forwardVec );
 916   axis.getColumn( 1, &upVec );
 917   axis.getColumn( 0, &rightVec );
 918
 919   Point2I pos = getPosition();
 920   F32 offsetx = pos.x + 20.0;
 921   F32 offsety = pos.y + getExtent().y - 42.0; // Take the status bar into account
 922   F32 scale = 15.0;
 923
 924   // Generate correct drawing order
 925   ColorI c1(255,0,0);
 926   ColorI c2(0,255,0);
 927   ColorI c3(0,0,255);
 928   ColorI tc;
 929   Point3F *p1, *p2, *p3, *tp;
 930   p1 = &rightVec;
 931   p2 = &upVec;
 932   p3 = &forwardVec;
 933   if(p3->y > p2->y)
 934   {
 935      tp = p2; tc = c2;
 936      p2 = p3; c2 = c3;
 937      p3 = tp; c3 = tc;
 938   }
 939   if(p2->y > p1->y)
 940   {
 941      tp = p1; tc = c1;
 942      p1 = p2; c1 = c2;
 943      p2 = tp; c2 = tc;
 944   }
 945
 946   PrimBuild::begin( GFXLineList, 6 );
 947      //*** Axis 1
 948      PrimBuild::color(c1);
 949      PrimBuild::vertex3f(offsetx, offsety, 0);
 950      PrimBuild::vertex3f(offsetx+p1->x*scale, offsety-p1->z*scale, 0);
 951
 952      //*** Axis 2
 953      PrimBuild::color(c2);
 954      PrimBuild::vertex3f(offsetx, offsety, 0);
 955      PrimBuild::vertex3f(offsetx+p2->x*scale, offsety-p2->z*scale, 0);
 956
 957      //*** Axis 3
 958      PrimBuild::color(c3);
 959      PrimBuild::vertex3f(offsetx, offsety, 0);
 960      PrimBuild::vertex3f(offsetx+p3->x*scale, offsety-p3->z*scale, 0);
 961   PrimBuild::end();
 962}
 963
 964void EditTSCtrl::renderGrid()
 965{
 966   if( !isOrthoDisplayType() )
 967      return;
 968
 969   GFXDEBUGEVENT_SCOPE( Editor_renderGrid, ColorI::WHITE );
 970
 971   // Calculate the displayed grid size based on view
 972   F32 drawnGridSize = mGridPlaneSize;
 973   F32 gridPixelSize = projectRadius(1.0f, mGridPlaneSize);
 974   if(gridPixelSize < mGridPlaneSizePixelBias)
 975   {
 976      U32 counter = 1;
 977      while(gridPixelSize < mGridPlaneSizePixelBias)
 978      {
 979         drawnGridSize = mGridPlaneSize * counter * 10.0f;
 980         gridPixelSize = projectRadius(1.0f, drawnGridSize);
 981
 982         ++counter;
 983
 984         // No infinite loops here
 985         if(counter > 1000)
 986            break;
 987      }
 988   }
 989
 990   F32 minorTickSize = 0;
 991   F32 gridSize = drawnGridSize;
 992   U32 minorTickMax = mGridPlaneMinorTicks + 1;
 993   if(minorTickMax > 0)
 994   {
 995      minorTickSize = drawnGridSize;
 996      gridSize = drawnGridSize * minorTickMax;
 997   }
 998
 999   // Build the view-based origin
1000   VectorF dir;
1001   smCamMatrix.getColumn( 1, &dir );
1002
1003   Point3F gridPlanePos = smCamPos + dir;
1004   Point2F size(mOrthoWidth + 2 * gridSize, mOrthoHeight + 2 * gridSize);
1005
1006   GFXStateBlockDesc desc;
1007   desc.setBlend( true );
1008   desc.setZReadWrite( true, false );
1009
1010   GFXDrawUtil::Plane plane = GFXDrawUtil::PlaneXY;
1011   switch( getDisplayType() )
1012   {
1013      case DisplayTypeTop:
1014      case DisplayTypeBottom:
1015         plane = GFXDrawUtil::PlaneXY;
1016         break;
1017
1018      case DisplayTypeLeft:
1019      case DisplayTypeRight:
1020         plane = GFXDrawUtil::PlaneYZ;
1021         break;
1022
1023      case DisplayTypeFront:
1024      case DisplayTypeBack:
1025         plane = GFXDrawUtil::PlaneXZ;
1026         break;
1027         
1028      default:
1029         break;
1030   }
1031
1032   GFX->getDrawUtil()->drawPlaneGrid( desc, gridPlanePos, size, Point2F( minorTickSize, minorTickSize ), mGridPlaneMinorTickColor, plane );
1033   GFX->getDrawUtil()->drawPlaneGrid( desc, gridPlanePos, size, Point2F( gridSize, gridSize ), mGridPlaneColor, plane );
1034}
1035
1036static void sceneBoundsCalcCallback(SceneObject* obj, void *key)
1037{
1038   // Early out for those objects that slipped through the mask check
1039   // because they belong to more than one type.
1040   if((obj->getTypeMask() & EditTSCtrl::smSceneBoundsMask) != 0)
1041      return;
1042
1043   if(obj->isGlobalBounds())
1044      return;
1045
1046   Box3F* bounds = (Box3F*)key;
1047
1048   Point3F min = obj->getWorldBox().minExtents;
1049   Point3F max = obj->getWorldBox().maxExtents;
1050
1051   #if 0 // Console messages in render loop lead to massive spam.
1052   if (min.z <= -5000.0f ||
1053       min.z >=  5000.0f)
1054       getName());
1055   #endif
1056
1057   bounds->minExtents.setMin(min);
1058   bounds->minExtents.setMin(max);
1059   bounds->maxExtents.setMax(min);
1060   bounds->maxExtents.setMax(max);
1061}
1062
1063bool EditTSCtrl::getCameraTransform(MatrixF* cameraMatrix)
1064{
1065   GameConnection* connection = dynamic_cast<GameConnection *>(NetConnection::getConnectionToServer());
1066   return (connection && connection->getControlCameraTransform(0.032f, cameraMatrix));
1067}
1068
1069void EditTSCtrl::computeSceneBounds(Box3F& bounds)
1070{
1071   bounds.minExtents.set(1e10, 1e10, 1e10);
1072   bounds.maxExtents.set(-1e10, -1e10, -1e10);
1073
1074   // Calculate the scene bounds
1075   gClientContainer.findObjects(~(smSceneBoundsMask), sceneBoundsCalcCallback, &bounds);
1076}
1077
1078bool EditTSCtrl::processCameraQuery(CameraQuery * query)
1079{
1080   if(mDisplayType == DisplayTypePerspective)
1081   {
1082      query->ortho = false;
1083   }
1084   else
1085   {
1086      query->ortho = true;
1087   }
1088
1089   if (getCameraTransform(&query->cameraMatrix))
1090   {
1091      query->farPlane = gClientSceneGraph->getVisibleDistance() * smVisibleDistanceScale;
1092      query->nearPlane = gClientSceneGraph->getNearClip();
1093      query->fov = mDegToRad(smCamFOV);
1094
1095      if(query->ortho)
1096      {
1097         MatrixF camRot(true);
1098         const F32 camBuffer = 1.0f;
1099         Point3F camPos = query->cameraMatrix.getPosition();
1100
1101         F32 isocamplanedist = 0.0f;
1102         if(mDisplayType == DisplayTypeIsometric)
1103         {
1104            const RectI& vp = GFX->getViewport();
1105            isocamplanedist = 0.25 * vp.extent.y * mSin(mIsoCamAngle);
1106         }
1107
1108         // Calculate the scene bounds
1109         Box3F sceneBounds;
1110         computeSceneBounds(sceneBounds);
1111
1112         if(!sceneBounds.isValidBox())
1113         {
1114            sceneBounds.maxExtents = camPos + smMinSceneBounds;
1115            sceneBounds.minExtents = camPos - smMinSceneBounds;
1116         }
1117         else
1118         {
1119            query->farPlane = getMax(smMinSceneBounds.x * 2.0f, (sceneBounds.maxExtents - sceneBounds.minExtents).len() + camBuffer * 2.0f + isocamplanedist);
1120         }
1121
1122         mRawCamPos = camPos;
1123         camPos += mOrthoCamTrans;
1124
1125         switch(mDisplayType)
1126         {
1127            case DisplayTypeTop:
1128               camRot.setColumn(0, Point3F(1.0, 0.0,  0.0));
1129               camRot.setColumn(1, Point3F(0.0, 0.0, -1.0));
1130               camRot.setColumn(2, Point3F(0.0, 1.0,  0.0));
1131               camPos.z = getMax(camPos.z + smMinSceneBounds.z, sceneBounds.maxExtents.z + camBuffer);
1132               break;
1133
1134            case DisplayTypeBottom:
1135               camRot.setColumn(0, Point3F(1.0,  0.0,  0.0));
1136               camRot.setColumn(1, Point3F(0.0,  0.0,  1.0));
1137               camRot.setColumn(2, Point3F(0.0, -1.0,  0.0));
1138               camPos.z = getMin(camPos.z - smMinSceneBounds.z, sceneBounds.minExtents.z - camBuffer);
1139               break;
1140
1141            case DisplayTypeFront:
1142               camRot.setColumn(0, Point3F(1.0, 0.0, 0.0));
1143               camRot.setColumn(1, Point3F(0.0, 1.0, 0.0));
1144               camRot.setColumn(2, Point3F(0.0, 0.0, 1.0));
1145               camPos.y = getMin(camPos.y - smMinSceneBounds.y, sceneBounds.minExtents.y - camBuffer);
1146               break;
1147
1148            case DisplayTypeBack:
1149               camRot.setColumn(0, Point3F(-1.0, 0.0, 0.0));
1150               camRot.setColumn(1, Point3F(0.0, -1.0, 0.0));
1151               camRot.setColumn(2, Point3F(0.0, 0.0, 1.0));
1152               camPos.y = getMax(camPos.y + smMinSceneBounds.y, sceneBounds.maxExtents.y + camBuffer);
1153               break;
1154
1155            case DisplayTypeLeft:
1156               camRot.setColumn(0, Point3F( 0.0, -1.0,  0.0));
1157               camRot.setColumn(1, Point3F( 1.0,  0.0,  0.0));
1158               camRot.setColumn(2, Point3F( 0.0,  0.0,  1.0));
1159               camPos.x = getMin(camPos.x - smMinSceneBounds.x, sceneBounds.minExtents.x - camBuffer);
1160               break;
1161
1162            case DisplayTypeRight:
1163               camRot.setColumn(0, Point3F( 0.0,  1.0,  0.0));
1164               camRot.setColumn(1, Point3F(-1.0,  0.0,  0.0));
1165               camRot.setColumn(2, Point3F( 0.0,  0.0,  1.0));
1166               camPos.x = getMax(camPos.x + smMinSceneBounds.x, sceneBounds.maxExtents.x + camBuffer);
1167               break;
1168
1169            case DisplayTypeIsometric:
1170               camPos.z = sceneBounds.maxExtents.z + camBuffer + isocamplanedist;
1171               MatrixF angle(EulerF(mIsoCamAngle, 0, 0));
1172               MatrixF rot(mIsoCamRot);
1173               camRot.mul(rot, angle);
1174               break;
1175         }
1176
1177         query->cameraMatrix = camRot;
1178         query->cameraMatrix.setPosition(camPos);
1179         query->headMatrix = query->cameraMatrix;
1180         query->fov = mOrthoFOV;
1181      }
1182
1183      smCamMatrix = query->cameraMatrix;
1184      smCamMatrix.getColumn(3,&smCamPos);
1185      smCamOrtho = query->ortho;
1186      smCamNearPlane = query->nearPlane;
1187
1188      return true;
1189   }
1190   return false;
1191}
1192
1193//------------------------------------------------------------------------------
1194DefineEngineMethod( EditTSCtrl, getDisplayType, S32, (),, "" )
1195{
1196   return object->getDisplayType();
1197}
1198
1199DefineEngineMethod( EditTSCtrl, setDisplayType, void, ( S32 displayType ),, "" )
1200{
1201   object->setDisplayType( displayType );
1202}
1203
1204DefineEngineMethod( EditTSCtrl, getOrthoFOV, F32, (),,
1205   "Return the FOV for orthographic views." )
1206{
1207   return object->getOrthoFOV();
1208}
1209
1210DefineEngineMethod( EditTSCtrl, setOrthoFOV, void, ( F32 fov ),,
1211   "Set the FOV for to use for orthographic views." )
1212{
1213   object->setOrthoFOV( fov );
1214}
1215
1216DefineEngineMethod( EditTSCtrl, renderBox, void, ( Point3F pos, Point3F size ),, "" )
1217{
1218   if( !object->mConsoleRendering || !object->mConsoleFillColor.alpha )
1219      return;
1220
1221   GFXStateBlockDesc desc;
1222   desc.setBlend( true );
1223
1224   Box3F box;
1225   box.set( size );
1226   box.setCenter( pos );
1227
1228   MatrixF camera = GFX->getWorldMatrix();
1229   camera.inverse();
1230
1231   if( box.isContained( camera.getPosition() ) )
1232      desc.setCullMode( GFXCullNone );
1233
1234   GFX->getDrawUtil()->drawCube( desc, size, pos, object->mConsoleFillColor );
1235}
1236
1237DefineEngineMethod(EditTSCtrl, renderSphere, void, ( Point3F pos, F32 radius, S32 sphereLevel ), ( 0 ), "" )
1238{
1239   if ( !object->mConsoleRendering || !object->mConsoleFillColor.alpha )
1240      return;
1241
1242   // TODO: We need to support subdivision levels in GFXDrawUtil!
1243   if ( sphereLevel <= 0 )
1244      sphereLevel = object->mConsoleSphereLevel;
1245
1246   GFXStateBlockDesc desc;
1247   desc.setBlend( true );
1248
1249   MatrixF camera = GFX->getWorldMatrix();
1250   camera.inverse();
1251   
1252   SphereF sphere( pos, radius );
1253   if( sphere.isContained( camera.getPosition() ) )
1254      desc.setCullMode( GFXCullNone );
1255
1256   GFX->getDrawUtil()->drawSphere( desc, radius, pos, object->mConsoleFillColor );
1257}
1258
1259DefineEngineMethod( EditTSCtrl, renderCircle, void, ( Point3F pos, Point3F normal, F32 radius, S32 segments ), ( 0 ), "" )
1260{
1261   if(!object->mConsoleRendering)
1262      return;
1263
1264   if(!object->mConsoleFrameColor.alpha && !object->mConsoleFillColor.alpha)
1265      return;
1266
1267   if ( segments <= 0 )
1268      segments = object->mConsoleCircleSegments;
1269
1270   normal.normalizeSafe();
1271
1272   AngAxisF aa;
1273
1274   F32 dotUp = mDot( normal, Point3F(0,0,1) );
1275   if ( dotUp == 1.0f )
1276      aa.set( Point3F(0,0,1), 0.0f );     // normal is 0,0,1
1277   else if ( dotUp == -1.0f )
1278      aa.set( Point3F(1,0,0), M_PI_F );   // normal is 0,0,-1
1279   else
1280   {
1281      mCross( normal, Point3F(0,0,1), &aa.axis );
1282      aa.axis.normalizeSafe();
1283      aa.angle = mAcos( mClampF( dotUp, -1.f, 1.f ) );
1284   }
1285
1286   MatrixF mat;
1287   aa.setMatrix(&mat);
1288
1289   F32 step = M_2PI / segments;
1290   F32 angle = 0.f;
1291
1292   Vector<Point3F> points(segments);
1293   for(U32 i = 0; i < segments; i++)
1294   {
1295      Point3F pnt(mCos(angle), mSin(angle), 0.f);
1296
1297      mat.mulP(pnt);
1298      pnt *= radius;
1299      pnt += pos;
1300
1301      points.push_front(pnt);
1302      angle += step;
1303   }
1304
1305   GFX->setStateBlock(object->mBlendSB);
1306
1307   // framed
1308   if(object->mConsoleFrameColor.alpha)
1309   {
1310      // TODO: Set GFX line width (when it exists) to the value of 'object->mConsoleLineWidth'
1311
1312      PrimBuild::color( object->mConsoleFrameColor );
1313
1314      PrimBuild::begin( GFXLineStrip, points.size() + 1 );
1315
1316      for( S32 i = 0; i < points.size(); i++ )
1317         PrimBuild::vertex3fv( points[i] );
1318
1319      // GFX does not have a LineLoop primitive, so connect the last line
1320      if( points.size() > 0 )
1321         PrimBuild::vertex3fv( points[0] );
1322
1323      PrimBuild::end();
1324
1325      // TODO: Reset GFX line width here
1326   }
1327
1328   // filled
1329   if(object->mConsoleFillColor.alpha)
1330   {
1331      PrimBuild::color( object->mConsoleFillColor );
1332
1333      PrimBuild::begin( GFXTriangleStrip, points.size() + 2 );
1334
1335      // Center point
1336      PrimBuild::vertex3fv( pos );
1337
1338      // Edge verts
1339      for( S32 i = 0; i < points.size(); i++ )
1340         PrimBuild::vertex3fv( points[i] );
1341
1342      PrimBuild::vertex3fv( points[0] );
1343
1344      PrimBuild::end();
1345   }
1346}
1347
1348DefineEngineMethod( EditTSCtrl, renderTriangle, void, ( Point3F a, Point3F b, Point3F c ),, "" )
1349{
1350   if(!object->mConsoleRendering)
1351      return;
1352
1353   if(!object->mConsoleFrameColor.alpha && !object->mConsoleFillColor.alpha)
1354      return;
1355
1356   const Point3F* pnts[3] = { &a, &b, &c };
1357
1358   GFX->setStateBlock(object->mBlendSB);
1359
1360   // frame
1361   if( object->mConsoleFrameColor.alpha )
1362   {
1363      PrimBuild::color( object->mConsoleFrameColor );
1364  
1365      // TODO: Set GFX line width (when it exists) to the value of 'object->mConsoleLineWidth'
1366
1367      PrimBuild::begin( GFXLineStrip, 4 );
1368         PrimBuild::vertex3fv( *pnts[0] );
1369         PrimBuild::vertex3fv( *pnts[1] );
1370         PrimBuild::vertex3fv( *pnts[2] );
1371         PrimBuild::vertex3fv( *pnts[0] );
1372      PrimBuild::end();
1373
1374      // TODO: Reset GFX line width here
1375   }
1376
1377   // fill
1378   if( object->mConsoleFillColor.alpha )
1379   {
1380      PrimBuild::color( object->mConsoleFillColor );
1381
1382      PrimBuild::begin( GFXTriangleList, 3 );
1383         PrimBuild::vertex3fv( *pnts[0] );
1384         PrimBuild::vertex3fv( *pnts[1] );
1385         PrimBuild::vertex3fv( *pnts[2] );
1386      PrimBuild::end();
1387   }
1388}
1389
1390DefineEngineMethod( EditTSCtrl, renderLine, void, ( Point3F start, Point3F end, F32 lineWidth ), ( 0 ), "" )
1391{
1392   if ( !object->mConsoleRendering || !object->mConsoleFrameColor.alpha )
1393      return;
1394
1395   // TODO: We don't support 3d lines with width... fix this!
1396   if ( lineWidth <= 0 )
1397      lineWidth = object->mConsoleLineWidth;
1398
1399   GFX->getDrawUtil()->drawLine( start, end, object->mConsoleFrameColor );
1400}
1401
1402DefineEngineMethod( EditTSCtrl, getGizmo, S32, (),, "" )
1403{
1404   return object->getGizmo()->getId();
1405}
1406
1407DefineEngineMethod( EditTSCtrl, isMiddleMouseDown, bool, (),, "" )
1408{
1409   return object->isMiddleMouseDown();
1410}
1411