guiDecalEditorCtrl.cpp
Engine/source/gui/worldEditor/guiDecalEditorCtrl.cpp
Public Functions
ConsoleDocClass(DBDeleteUndoAction , "@brief Decal Datablock Delete Undo <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Actions\n\n</a>" "Not intended <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> game development, <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> editors or internal use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only.\n\n</a> " " @internal" )
ConsoleDocClass(DBRetargetUndoAction , "@brief Decal Datablock Retarget Undo <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Actions\n\n</a>" "Not intended <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> game development, <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> editors or internal use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only.\n\n</a> " " @internal" )
ConsoleDocClass(DICreateUndoAction , "@brief Decal Instance Create Undo <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Actions\n\n</a>" "Not intended <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> game development, <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> editors or internal use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only.\n\n</a> " " @internal" )
ConsoleDocClass(DIDeleteUndoAction , "@brief Decal Instance Delete Undo <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Actions\n\n</a>" "Not intended <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> game development, <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> editors or internal use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only.\n\n</a> " " @internal" )
ConsoleDocClass(GuiDecalEditorCtrl , "@brief The base class <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the Decal Editor <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tool\n\n</a>" "Editor use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only.\n\n</a>" "@internal" )
DefineEngineMethod(GuiDecalEditorCtrl , deleteDecalDatablock , void , (const char *datablock) , "deleteSelectedDecalDatablock( <a href="/coding/class/classstring/">String</a> datablock )" )
DefineEngineMethod(GuiDecalEditorCtrl , deleteSelectedDecal , void , () , "deleteSelectedDecal()" )
DefineEngineMethod(GuiDecalEditorCtrl , editDecalDetails , void , (U32 id, Point3F pos, Point3F tan, F32 size) , "editDecalDetails( <a href="/coding/file/types_8h/#types_8h_1a57a2244776e01ad620c556de58eb7880">S32</a> )()" )
DefineEngineMethod(GuiDecalEditorCtrl , getDecalCount , S32 , () , "getDecalCount()" )
DefineEngineMethod(GuiDecalEditorCtrl , getDecalLookupName , const char * , (U32 id) , "getDecalLookupName( <a href="/coding/file/types_8h/#types_8h_1a57a2244776e01ad620c556de58eb7880">S32</a> )()" )
DefineEngineMethod(GuiDecalEditorCtrl , getDecalTransform , const char * , (U32 id) , "getDecalTransform()" )
DefineEngineMethod(GuiDecalEditorCtrl , getMode , const char * , () , "getMode()" )
DefineEngineMethod(GuiDecalEditorCtrl , getSelectionCount , S32 , () , "" )
DefineEngineMethod(GuiDecalEditorCtrl , retargetDecalDatablock , void , (const char *dbFrom, const char *dbTo) , "" )
DefineEngineMethod(GuiDecalEditorCtrl , selectDecal , void , (U32 id) , "selectDecal( <a href="/coding/file/types_8h/#types_8h_1a57a2244776e01ad620c556de58eb7880">S32</a> )()" )
DefineEngineMethod(GuiDecalEditorCtrl , setMode , void , (String newMode) , "setMode( <a href="/coding/class/classstring/">String</a> <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> )()" )
Detailed Description
Public Functions
ConsoleDocClass(DBDeleteUndoAction , "@brief Decal Datablock Delete Undo <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Actions\n\n</a>" "Not intended <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> game development, <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> editors or internal use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only.\n\n</a> " " @internal" )
ConsoleDocClass(DBRetargetUndoAction , "@brief Decal Datablock Retarget Undo <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Actions\n\n</a>" "Not intended <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> game development, <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> editors or internal use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only.\n\n</a> " " @internal" )
ConsoleDocClass(DICreateUndoAction , "@brief Decal Instance Create Undo <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Actions\n\n</a>" "Not intended <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> game development, <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> editors or internal use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only.\n\n</a> " " @internal" )
ConsoleDocClass(DIDeleteUndoAction , "@brief Decal Instance Delete Undo <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Actions\n\n</a>" "Not intended <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> game development, <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> editors or internal use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only.\n\n</a> " " @internal" )
ConsoleDocClass(GuiDecalEditorCtrl , "@brief The base class <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the Decal Editor <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tool\n\n</a>" "Editor use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only.\n\n</a>" "@internal" )
DefineEngineMethod(GuiDecalEditorCtrl , deleteDecalDatablock , void , (const char *datablock) , "deleteSelectedDecalDatablock( <a href="/coding/class/classstring/">String</a> datablock )" )
DefineEngineMethod(GuiDecalEditorCtrl , deleteSelectedDecal , void , () , "deleteSelectedDecal()" )
DefineEngineMethod(GuiDecalEditorCtrl , editDecalDetails , void , (U32 id, Point3F pos, Point3F tan, F32 size) , "editDecalDetails( <a href="/coding/file/types_8h/#types_8h_1a57a2244776e01ad620c556de58eb7880">S32</a> )()" )
DefineEngineMethod(GuiDecalEditorCtrl , getDecalCount , S32 , () , "getDecalCount()" )
DefineEngineMethod(GuiDecalEditorCtrl , getDecalLookupName , const char * , (U32 id) , "getDecalLookupName( <a href="/coding/file/types_8h/#types_8h_1a57a2244776e01ad620c556de58eb7880">S32</a> )()" )
DefineEngineMethod(GuiDecalEditorCtrl , getDecalTransform , const char * , (U32 id) , "getDecalTransform()" )
DefineEngineMethod(GuiDecalEditorCtrl , getMode , const char * , () , "getMode()" )
DefineEngineMethod(GuiDecalEditorCtrl , getSelectionCount , S32 , () , "" )
DefineEngineMethod(GuiDecalEditorCtrl , retargetDecalDatablock , void , (const char *dbFrom, const char *dbTo) , "" )
DefineEngineMethod(GuiDecalEditorCtrl , selectDecal , void , (U32 id) , "selectDecal( <a href="/coding/file/types_8h/#types_8h_1a57a2244776e01ad620c556de58eb7880">S32</a> )()" )
DefineEngineMethod(GuiDecalEditorCtrl , setMode , void , (String newMode) , "setMode( <a href="/coding/class/classstring/">String</a> <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> )()" )
IMPLEMENT_CONOBJECT(DBDeleteUndoAction )
IMPLEMENT_CONOBJECT(DBRetargetUndoAction )
IMPLEMENT_CONOBJECT(DICreateUndoAction )
IMPLEMENT_CONOBJECT(DIDeleteUndoAction )
IMPLEMENT_CONOBJECT(GuiDecalEditorCtrl )
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#ifndef TORQUE_TGB_ONLY 25 26#include "guiDecalEditorCtrl.h" 27#include "platform/platform.h" 28 29#include "console/consoleTypes.h" 30#include "console/engineAPI.h" 31#include "scene/sceneManager.h" 32#include "collision/collision.h" 33#include "math/util/frustum.h" 34#include "gfx/gfxPrimitiveBuffer.h" 35#include "gfx/gfxTextureHandle.h" 36#include "gfx/gfxTransformSaver.h" 37#include "gfx/primBuilder.h" 38#include "gfx/gfxDrawUtil.h" 39#include "gui/core/guiCanvas.h" 40#include "gui/buttons/guiButtonCtrl.h" 41#include "gui/worldEditor/gizmo.h" 42#include "T3D/decal/decalManager.h" 43#include "T3D/decal/decalInstance.h" 44#include "gui/worldEditor/undoActions.h" 45 46IMPLEMENT_CONOBJECT(GuiDecalEditorCtrl); 47 48ConsoleDocClass( GuiDecalEditorCtrl, 49 "@brief The base class for the Decal Editor tool\n\n" 50 "Editor use only.\n\n" 51 "@internal" 52); 53 54bool GuiDecalEditorCtrl::smRenderDecalPixelSize = false; 55 56GuiDecalEditorCtrl::GuiDecalEditorCtrl() 57{ 58 mSELDecal = NULL; 59 mHLDecal = NULL; 60 mCurrentDecalData = NULL; 61 mMode = "AddDecalMode"; 62 mPerformedDragCopy = false; 63} 64 65GuiDecalEditorCtrl::~GuiDecalEditorCtrl() 66{ 67 // nothing to do 68} 69 70bool GuiDecalEditorCtrl::onAdd() 71{ 72 if( !Parent::onAdd() ) 73 return false; 74 75 return true; 76} 77 78void GuiDecalEditorCtrl::initPersistFields() 79{ 80 addField( "currentDecalData", TYPEID< DecalData >(), Offset( mCurrentDecalData, GuiDecalEditorCtrl ) ); 81 82 Parent::initPersistFields(); 83} 84 85void GuiDecalEditorCtrl::consoleInit() 86{ 87 Con::addVariable( "$DecalEditor::renderPixelSize", TypeBool, &smRenderDecalPixelSize, 88 "Set true to render the pixel size as on overlay on the selected decal instance. " 89 "This is the value used to fade distant decals and is intended to help the user adjust " 90 "the values of DecalData::pixelSizeStartFade and pixelSizeEndFade.\n\n" 91 "@internal" ); 92 93 Parent::consoleInit(); 94} 95 96void GuiDecalEditorCtrl::onEditorDisable() 97{ 98 // Tools are not deleted/recreated between missions, but decals instances 99 // ARE. So we must release any references. 100 mSELDecal = NULL; 101 mHLDecal = NULL; 102} 103 104bool GuiDecalEditorCtrl::onWake() 105{ 106 if ( !Parent::onWake() ) 107 return false; 108 109 110 111 return true; 112} 113 114void GuiDecalEditorCtrl::onSleep() 115{ 116 Parent::onSleep(); 117} 118 119void GuiDecalEditorCtrl::get3DCursor( GuiCursor *&cursor, 120 bool &visible, 121 const Gui3DMouseEvent &event_ ) 122{ 123 cursor = NULL; 124 visible = false; 125 126 GuiCanvas *root = getRoot(); 127 if ( !root ) 128 return; 129 130 S32 currCursor = PlatformCursorController::curArrow; 131 132 if ( root->mCursorChanged == currCursor ) 133 return; 134 135 PlatformWindow *window = root->getPlatformWindow(); 136 PlatformCursorController *controller = window->getCursorController(); 137 138 // We've already changed the cursor, 139 // so set it back before we change it again. 140 if( root->mCursorChanged != -1) 141 controller->popCursor(); 142 143 // Now change the cursor shape 144 controller->pushCursor(currCursor); 145 root->mCursorChanged = currCursor; 146} 147 148void GuiDecalEditorCtrl::on3DMouseDown(const Gui3DMouseEvent & event) 149{ 150 mPerformedDragCopy = false; 151 152 if ( !isFirstResponder() ) 153 setFirstResponder(); 154 155 bool dblClick = ( event.mouseClickCount > 1 ); 156 157 // Gather selected decal information 158 RayInfo ri; 159 bool hit = getRayInfo( event, &ri ); 160 161 Point3F start = event.pos; 162 Point3F end = start + event.vec * 3000.0f; // use visible distance here?? 163 164 DecalInstance *pDecal = gDecalManager->raycast( start, end ); 165 166 if( mMode.compare("AddDecalMode") != 0 ) 167 { 168 if ( mSELDecal ) 169 { 170 // If our click hit the gizmo we are done. 171 if ( mGizmo->getSelection() != Gizmo::None ) 172 { 173 mGizmo->on3DMouseDown( event ); 174 175 char returnBuffer[256]; 176 dSprintf(returnBuffer, sizeof(returnBuffer), "%f %f %f %f %f %f %f", 177 mSELDecal->mPosition.x, mSELDecal->mPosition.y, mSELDecal->mPosition.z, 178 mSELDecal->mTangent.x, mSELDecal->mTangent.y, mSELDecal->mTangent.z, 179 mSELDecal->mSize); 180 181 Con::executef( this, "prepGizmoTransform", Con::getIntArg(mSELDecal->mId), returnBuffer ); 182 183 return; 184 } 185 } 186 187 if ( mHLDecal && pDecal == mHLDecal ) 188 { 189 mHLDecal = NULL; 190 selectDecal( pDecal ); 191 192 if ( isMethod( "onSelectInstance" ) ) 193 { 194 char idBuf[512]; 195 dSprintf(idBuf, 512, "%i", pDecal->mId); 196 Con::executef( this, "onSelectInstance", String(idBuf).c_str(), pDecal->mDataBlock->lookupName.c_str() ); 197 } 198 199 return; 200 } 201 else if ( hit && !pDecal) 202 { 203 if ( dblClick ) 204 setMode( String("AddDecalMode"), true ); 205 206 return; 207 } 208 } 209 else 210 { 211 // If we accidently hit a decal, then bail(probably an accident). If the use hits the decal twice, 212 // then boot them into selection mode and select the decal. 213 if ( mHLDecal && pDecal == mHLDecal ) 214 { 215 if ( dblClick ) 216 { 217 mHLDecal = NULL; 218 selectDecal( pDecal ); 219 220 if ( isMethod( "onSelectInstance" ) ) 221 { 222 char idBuf[512]; 223 dSprintf(idBuf, 512, "%i", pDecal->mId); 224 Con::executef( this, "onSelectInstance", String(idBuf).c_str(), pDecal->mDataBlock->lookupName.c_str() ); 225 } 226 setMode( String("SelectDecalMode"), true ); 227 } 228 return; 229 } 230 231 if ( hit && mCurrentDecalData ) // Create a new decal... 232 { 233 U8 flags = PermanentDecal | SaveDecal; 234 235 DecalInstance *decalInst = gDecalManager->addDecal( ri.point, ri.normal, 0.0f, mCurrentDecalData, 1.0f, -1, flags ); 236 237 if ( decalInst ) 238 { 239 // Give the decal an id 240 decalInst->mId = gDecalManager->mDecalInstanceVec.size(); 241 gDecalManager->mDecalInstanceVec.push_back(decalInst); 242 243 selectDecal( decalInst ); 244 245 // Grab the mission editor undo manager. 246 UndoManager *undoMan = NULL; 247 if ( !Sim::findObject( "EUndoManager", undoMan ) ) 248 { 249 Con::errorf( "GuiMeshRoadEditorCtrl::on3DMouseDown() - EUndoManager not found!" ); 250 return; 251 } 252 253 // Create the UndoAction. 254 DICreateUndoAction *action = new DICreateUndoAction("Create Decal"); 255 action->addDecal( *decalInst ); 256 257 action->mEditor = this; 258 // Submit it. 259 undoMan->addAction( action ); 260 261 if ( isMethod( "onCreateInstance" ) ) 262 { 263 char buffer[512]; 264 dSprintf(buffer, 512, "%i", decalInst->mId); 265 Con::executef( this, "onCreateInstance", buffer, decalInst->mDataBlock->lookupName.c_str()); 266 } 267 } 268 269 return; 270 } 271 } 272 273 if ( !mSELDecal ) 274 return; 275} 276 277void GuiDecalEditorCtrl::on3DRightMouseDown(const Gui3DMouseEvent & event) 278{ 279 //mIsPanning = true; 280 //mGizmo->on3DRightMouseDown( event ); 281} 282 283void GuiDecalEditorCtrl::on3DRightMouseUp(const Gui3DMouseEvent & event) 284{ 285 //mIsPanning = false; 286// mGizmo->on3DRightMouseUp( event ); 287} 288 289void GuiDecalEditorCtrl::on3DMouseUp(const Gui3DMouseEvent & event) 290{ 291 if ( mSELDecal ) 292 { 293 if ( mGizmo->isDirty() ) 294 { 295 char returnBuffer[256]; 296 dSprintf(returnBuffer, sizeof(returnBuffer), "%f %f %f %f %f %f %f", 297 mSELDecal->mPosition.x, mSELDecal->mPosition.y, mSELDecal->mPosition.z, 298 mSELDecal->mTangent.x, mSELDecal->mTangent.y, mSELDecal->mTangent.z, 299 mSELDecal->mSize); 300 301 Con::executef( this, "completeGizmoTransform", Con::getIntArg(mSELDecal->mId), returnBuffer ); 302 303 mGizmo->markClean(); 304 } 305 306 mGizmo->on3DMouseUp( event ); 307 } 308} 309 310void GuiDecalEditorCtrl::on3DMouseMove(const Gui3DMouseEvent & event) 311{ 312 if ( mSELDecal ) 313 mGizmo->on3DMouseMove( event ); 314 315 RayInfo ri; 316 if ( !getRayInfo( event, &ri ) ) 317 return; 318 319 Point3F start = event.pos; 320 Point3F end = start + event.vec * 3000.0f; // use visible distance here?? 321 322 DecalInstance *pDecal = gDecalManager->raycast( start, end ); 323 324 if ( pDecal && pDecal != mSELDecal ) 325 mHLDecal = pDecal; 326 else if ( !pDecal ) 327 mHLDecal = NULL; 328} 329 330void GuiDecalEditorCtrl::on3DMouseDragged(const Gui3DMouseEvent & event) 331{ 332 if ( !mSELDecal ) 333 return; 334 335 // Doing a drag copy of the decal? 336 if ( event.modifier & SI_SHIFT && !mPerformedDragCopy ) 337 { 338 mPerformedDragCopy = true; 339 340 DecalInstance *newDecal = gDecalManager->addDecal( mSELDecal->mPosition, 341 mSELDecal->mNormal, 342 0.0f, 343 mSELDecal->mDataBlock, 344 1.0f, 345 -1, 346 PermanentDecal | SaveDecal ); 347 348 newDecal->mTangent = mSELDecal->mTangent; 349 newDecal->mSize = mSELDecal->mSize; 350 newDecal->mTextureRectIdx = mSELDecal->mTextureRectIdx; 351 352 // TODO: This is crazy... we should move this sort of tracking 353 // inside of the decal manager... IdDecal flag maybe or just a 354 // byproduct of PermanentDecal? 355 // 356 newDecal->mId = gDecalManager->mDecalInstanceVec.size(); 357 gDecalManager->mDecalInstanceVec.push_back( newDecal ); 358 359 selectDecal( newDecal ); 360 361 // Grab the mission editor undo manager. 362 UndoManager *undoMan = NULL; 363 if ( Sim::findObject( "EUndoManager", undoMan ) ) 364 { 365 // Create the UndoAction. 366 DICreateUndoAction *action = new DICreateUndoAction("Create Decal"); 367 action->addDecal( *mSELDecal ); 368 action->mEditor = this; 369 undoMan->addAction( action ); 370 371 if ( isMethod( "onCreateInstance" ) ) 372 { 373 char buffer[512]; 374 dSprintf( buffer, 512, "%i", mSELDecal->mId ); 375 Con::executef( this, "onCreateInstance", buffer, mSELDecal->mDataBlock->lookupName.c_str()); 376 } 377 } 378 } 379 380 // Update the Gizmo. 381 if (mGizmo->getSelection() != Gizmo::None) 382 { 383 mGizmo->on3DMouseDragged( event ); 384 385 // Pull out the Gizmo transform 386 // and position. 387 const MatrixF &gizmoMat = mGizmo->getTransform(); 388 const Point3F &gizmoPos = gizmoMat.getPosition(); 389 390 // Get the new projection vector. 391 VectorF upVec, rightVec; 392 gizmoMat.getColumn( 0, &rightVec ); 393 gizmoMat.getColumn( 2, &upVec ); 394 395 const Point3F &scale = mGizmo->getScale(); 396 397 // Assign the appropriate changed value back to the decal. 398 if ( mGizmo->getMode() == ScaleMode ) 399 { 400 // Save old size. 401 const F32 oldSize = mSELDecal->mSize; 402 403 // Set new size. 404 mSELDecal->mSize = ( scale.x + scale.y ) * 0.5f; 405 406 // See if the decal properly clips/projects at this size. If not, 407 // stick to the old size. 408 mSELEdgeVerts.clear(); 409 if ( !gDecalManager->clipDecal( mSELDecal, &mSELEdgeVerts ) ) 410 mSELDecal->mSize = oldSize; 411 } 412 else if ( mGizmo->getMode() == MoveMode ) 413 mSELDecal->mPosition = gizmoPos; 414 else if ( mGizmo->getMode() == RotateMode ) 415 { 416 mSELDecal->mNormal = upVec; 417 mSELDecal->mTangent = rightVec; 418 } 419 420 gDecalManager->notifyDecalModified( mSELDecal ); 421 422 Con::executef( this, "syncNodeDetails" ); 423 } 424} 425 426void GuiDecalEditorCtrl::on3DMouseEnter(const Gui3DMouseEvent & event) 427{ 428 // nothing to do 429} 430 431void GuiDecalEditorCtrl::on3DMouseLeave(const Gui3DMouseEvent & event) 432{ 433 // nothing to do 434} 435 436void GuiDecalEditorCtrl::updateGuiInfo() 437{ 438 // nothing to do 439} 440 441void GuiDecalEditorCtrl::onRender( Point2I offset, const RectI &updateRect ) 442{ 443 Parent::onRender( offset, updateRect ); 444} 445 446void GuiDecalEditorCtrl::renderGui( Point2I offset, const RectI &updateRect ) 447{ 448 Parent::renderGui( offset, updateRect ); 449 450 PROFILE_SCOPE( GuiDecalEditorCtrl_renderGui ); 451 452 // Show the pixelSize of the selected decal as a text overlay. 453 if ( smRenderDecalPixelSize && mSELDecal != NULL ) 454 { 455 const F32 pixelSize = mSELDecal->calcPixelSize( mSaveViewport.extent.y, mLastCameraQuery.cameraMatrix.getPosition(), mSaveWorldToScreenScale.y ); 456 457 // Find position onscreen to render the text. 458 Point3F screenPos; 459 bool onScreen = project( mSELDecal->mPosition, &screenPos ); 460 461 if ( onScreen ) 462 { 463 // It is extremely annoying to require the GuiProfile to have a font 464 // or to create one within the decal editor for only this single use, 465 // so we instead rely on the fact that we already have a Gizmo, that 466 // all Gizmo's have a GizmoProfile, and that GizmoProfile has a font. 467 GFont *font = mGizmo->getProfile()->font; 468 469 // Might as well use some colors defined in GizmoProfile too instead 470 // of just hardcoding it here. 471 const ColorI bgColor = mGizmo->getProfile()->inActiveColor; 472 const ColorI textColor = mGizmo->getProfile()->activeColor; 473 474 // Note: This mostly mirrors the way WorldEditor renders popupText for 475 // the gizmo during a drag operation, consider unifying this into a utility method. 476 477 char buf[256]; 478 dSprintf( buf, 256, "%0.3f", pixelSize ); 479 480 const U32 width = font->getStrWidth((const UTF8 *)buf);; 481 const Point2I posi( (U32)screenPos.x, (U32)screenPos.y + 12 ); 482 const Point2I minPt(posi.x - width / 2 - 2, posi.y - 1); 483 const Point2I maxPt(posi.x + width / 2 + 2, posi.y + font->getHeight() + 1); 484 485 GFXDrawUtil *drawer = GFX->getDrawUtil(); 486 drawer->drawRectFill( minPt, maxPt, bgColor ); 487 GFX->getDrawUtil()->setBitmapModulation( textColor ); 488 GFX->getDrawUtil()->drawText( mProfile->mFont, Point2I( posi.x - width / 2, posi.y ), buf ); 489 } 490 } 491} 492 493void GuiDecalEditorCtrl::renderScene(const RectI & updateRect) 494{ 495 PROFILE_SCOPE( GuiDecalEditorCtrl_renderScene ); 496 497 GFXTransformSaver saver; 498 499 ColorI hlColor(0,255,0,255); 500 ColorI regColor(255,0,0,255); 501 ColorI selColor(0,0,255,255); 502 ColorI color; 503 504 GFXDrawUtil *drawUtil = GFX->getDrawUtil(); 505 506 GFXStateBlockDesc desc; 507 desc.setBlend( true ); 508 desc.setZReadWrite( true, false ); 509 510 // Draw 3D stuff here. 511 if ( mSELDecal ) 512 { 513 mGizmo->renderGizmo( mLastCameraQuery.cameraMatrix, mLastCameraQuery.fov ); 514 515 mSELEdgeVerts.clear(); 516 if ( gDecalManager->clipDecal( mSELDecal, &mSELEdgeVerts ) ) 517 _renderDecalEdge( mSELEdgeVerts, ColorI( 255, 255, 255, 255 ) ); 518 519 const F32 &decalSize = mSELDecal->mSize; 520 Point3F boxSize( decalSize, decalSize, decalSize ); 521 522 MatrixF worldMat( true ); 523 mSELDecal->getWorldMatrix( &worldMat, true ); 524 525 drawUtil->drawObjectBox( desc, boxSize, mSELDecal->mPosition, worldMat, ColorI( 255, 255, 255, 255 ) ); 526 } 527 528 if ( mHLDecal ) 529 { 530 mHLEdgeVerts.clear(); 531 if ( gDecalManager->clipDecal( mHLDecal, &mHLEdgeVerts ) ) 532 _renderDecalEdge( mHLEdgeVerts, ColorI( 255, 255, 255, 255 ) ); 533 534 const F32 &decalSize = mHLDecal->mSize; 535 Point3F boxSize( decalSize, decalSize, decalSize ); 536 537 MatrixF worldMat( true ); 538 mHLDecal->getWorldMatrix( &worldMat, true ); 539 540 drawUtil->drawObjectBox( desc, boxSize, mHLDecal->mPosition, worldMat, ColorI( 255, 255, 255, 255 ) ); 541 } 542} 543 544void GuiDecalEditorCtrl::forceRedraw( DecalInstance * decalInstance ) 545{ 546 // This should be redundant because the decal is already reclipped 547 // on each frame. Also it is not possible execute rendering code like 548 // this in response to UI events from script. 549 /* 550 if ( !decalInstance ) 551 return; 552 553 GFXDrawUtil *drawUtil = GFX->getDrawUtil(); 554 GFXStateBlockDesc desc; 555 desc.setBlend( true ); 556 desc.setZReadWrite( true, false ); 557 558 Vector<Point3F> verts; 559 verts.clear(); 560 if ( gDecalManager->clipDecal( decalInstance, &verts ) ) 561 if ( gDecalManager->clipDecal( decalInstance, &verts ) ) 562 _renderDecalEdge( verts, ColorI( 255, 255, 255, 255 ) ); 563 564 const F32 &decalSize = decalInstance->mSize; 565 Point3F boxSize( decalSize, decalSize, decalSize ); 566 567 MatrixF worldMat( true ); 568 decalInstance->getWorldMatrix( &worldMat, true ); 569 570 drawUtil->drawObjectBox( desc, boxSize, decalInstance->mPosition, worldMat, ColorI( 255, 255, 255, 255 ) ); 571 */ 572} 573 574void GuiDecalEditorCtrl::_renderDecalEdge( const Vector<Point3F> &verts, const ColorI &color ) 575{ 576 U32 vertCount = verts.size(); 577 578 GFXTransformSaver saver; 579 580 PrimBuild::color( color ); 581 582 Point3F endPt( 0, 0, 0 ); 583 for ( U32 i = 0; i < vertCount; i++ ) 584 { 585 const Point3F &vert = verts[i]; 586 if ( i + 1 < vertCount ) 587 endPt = verts[i + 1]; 588 else 589 break; 590 591 PrimBuild::begin( GFXLineList, 2 ); 592 593 PrimBuild::vertex3f( vert.x, vert.y, vert.z ); 594 PrimBuild::vertex3f( endPt.x, endPt.y, endPt.z ); 595 596 PrimBuild::end(); 597 } 598} 599 600bool GuiDecalEditorCtrl::getRayInfo( const Gui3DMouseEvent & event, RayInfo *rInfo ) 601{ 602 Point3F startPnt = event.pos; 603 Point3F endPnt = event.pos + event.vec * 3000.0f; 604 605 bool hit; 606 607 hit = gServerContainer.castRayRendered( startPnt, endPnt, STATIC_COLLISION_TYPEMASK, rInfo ); 608 609 return hit; 610} 611 612void GuiDecalEditorCtrl::selectDecal( DecalInstance *decalInst ) 613{ 614 // If id is zero or invalid we set the selected decal to null 615 // which is correct. 616 mSELDecal = decalInst; 617 618 if ( decalInst ) 619 setGizmoFocus( decalInst ); 620} 621 622void GuiDecalEditorCtrl::deleteSelectedDecal() 623{ 624 if ( !mSELDecal ) 625 return; 626 627 // Grab the mission editor undo manager. 628 UndoManager *undoMan = NULL; 629 if ( !Sim::findObject( "EUndoManager", undoMan ) ) 630 { 631 Con::errorf( "GuiMeshRoadEditorCtrl::on3DMouseDown() - EUndoManager not found!" ); 632 return; 633 } 634 635 // Create the UndoAction. 636 DIDeleteUndoAction *action = new DIDeleteUndoAction("Delete Decal"); 637 action->deleteDecal( *mSELDecal ); 638 639 action->mEditor = this; 640 // Submit it. 641 undoMan->addAction( action ); 642 643 if ( isMethod( "onDeleteInstance" ) ) 644 { 645 char buffer[512]; 646 dSprintf(buffer, 512, "%i", mSELDecal->mId); 647 Con::executef( this, "onDeleteInstance", String(buffer).c_str(), mSELDecal->mDataBlock->lookupName.c_str() ); 648 } 649 650 gDecalManager->removeDecal( mSELDecal ); 651 mSELDecal = NULL; 652} 653 654void GuiDecalEditorCtrl::deleteDecalDatablock( String lookupName ) 655{ 656 DecalData * datablock = dynamic_cast<DecalData*> ( Sim::findObject(lookupName.c_str()) ); 657 if( !datablock ) 658 return; 659 660 // Grab the mission editor undo manager. 661 UndoManager *undoMan = NULL; 662 if ( !Sim::findObject( "EUndoManager", undoMan ) ) 663 { 664 Con::errorf( "GuiMeshRoadEditorCtrl::on3DMouseDown() - EUndoManager not found!" ); 665 return; 666 } 667 668 // Create the UndoAction. 669 DBDeleteUndoAction *action = new DBDeleteUndoAction("Delete Decal Datablock"); 670 action->mEditor = this; 671 action->mDatablockId = datablock->getId(); 672 673 Vector<DecalInstance*> mDecalQueue; 674 Vector<DecalInstance *>::iterator iter; 675 mDecalQueue.clear(); 676 const Vector<DecalSphere*> &grid = gDecalManager->getDecalDataFile()->getSphereList(); 677 678 for ( U32 i = 0; i < grid.size(); i++ ) 679 { 680 const DecalSphere *decalSphere = grid[i]; 681 mDecalQueue.merge( decalSphere->mItems ); 682 } 683 684 for ( iter = mDecalQueue.begin();iter != mDecalQueue.end();iter++ ) 685 { 686 if( !(*iter) ) 687 continue; 688 689 if( (*iter)->mDataBlock->lookupName.compare( lookupName ) == 0 ) 690 { 691 if( (*iter)->mId != -1 ) 692 { 693 //make sure to call onDeleteInstance as well 694 if ( isMethod( "onDeleteInstance" ) ) 695 { 696 char buffer[512]; 697 dSprintf(buffer, 512, "%i", (*iter)->mId); 698 Con::executef( this, "onDeleteInstance", String(buffer).c_str(), (*iter)->mDataBlock->lookupName.c_str() ); 699 } 700 701 action->deleteDecal( *(*iter) ); 702 703 if( mSELDecal == (*iter) ) 704 mSELDecal = NULL; 705 706 if( mHLDecal == (*iter) ) 707 mHLDecal = NULL; 708 } 709 gDecalManager->removeDecal( (*iter) ); 710 } 711 } 712 713 undoMan->addAction( action ); 714 715 mCurrentDecalData = NULL; 716} 717 718void GuiDecalEditorCtrl::retargetDecalDatablock( String dbFrom, String dbTo ) 719{ 720 DecalData * ptrFrom = dynamic_cast<DecalData*> ( Sim::findObject(dbFrom.c_str()) ); 721 DecalData * ptrTo = dynamic_cast<DecalData*> ( Sim::findObject(dbTo.c_str()) ); 722 723 if( !ptrFrom || !ptrTo ) 724 return; 725 726 // Grab the mission editor undo manager. 727 UndoManager *undoMan = NULL; 728 if ( !Sim::findObject( "EUndoManager", undoMan ) ) 729 { 730 Con::errorf( "GuiMeshRoadEditorCtrl::on3DMouseDown() - EUndoManager not found!" ); 731 return; 732 } 733 734 // Create the UndoAction. 735 DBRetargetUndoAction *action = new DBRetargetUndoAction("Retarget Decal Datablock"); 736 action->mEditor = this; 737 action->mDBFromId = ptrFrom->getId(); 738 action->mDBToId = ptrTo->getId(); 739 740 Vector<DecalInstance*> mDecalQueue; 741 Vector<DecalInstance *>::iterator iter; 742 mDecalQueue.clear(); 743 const Vector<DecalSphere*> &grid = gDecalManager->getDecalDataFile()->getSphereList(); 744 for ( U32 i = 0; i < grid.size(); i++ ) 745 { 746 const DecalSphere *decalSphere = grid[i]; 747 mDecalQueue.merge( decalSphere->mItems ); 748 } 749 750 for ( iter = mDecalQueue.begin();iter != mDecalQueue.end();iter++ ) 751 { 752 if( !(*iter) ) 753 continue; 754 755 if( (*iter)->mDataBlock->lookupName.compare( dbFrom ) == 0 ) 756 { 757 if( (*iter)->mId != -1 ) 758 { 759 action->retargetDecal((*iter)); 760 (*iter)->mDataBlock = ptrTo; 761 forceRedraw((*iter)); 762 } 763 } 764 } 765 766 undoMan->addAction( action ); 767} 768 769void GuiDecalEditorCtrl::setMode( String mode, bool sourceShortcut = false ) 770{ 771 if( mode.compare("SelectDecalMode") == 0) 772 mGizmo->getProfile()->mode = NoneMode; 773 else if( mode.compare("AddDecalMode") == 0) 774 mGizmo->getProfile()->mode = NoneMode; 775 else if( mode.compare("MoveDecalMode") == 0) 776 mGizmo->getProfile()->mode = MoveMode; 777 else if( mode.compare("RotateDecalMode") == 0) 778 mGizmo->getProfile()->mode = RotateMode; 779 else if( mode.compare("ScaleDecalMode") == 0) 780 mGizmo->getProfile()->mode = ScaleMode; 781 782 mMode = mode; 783 784 if( sourceShortcut ) 785 Con::executef( this, "paletteSync", mMode ); 786} 787 788DefineEngineMethod( GuiDecalEditorCtrl, deleteSelectedDecal, void, (), , "deleteSelectedDecal()" ) 789{ 790 object->deleteSelectedDecal(); 791} 792 793DefineEngineMethod( GuiDecalEditorCtrl, deleteDecalDatablock, void, ( const char * datablock ), , "deleteSelectedDecalDatablock( String datablock )" ) 794{ 795 String lookupName( datablock ); 796 if( lookupName == String::EmptyString ) 797 return; 798 799 object->deleteDecalDatablock( lookupName ); 800} 801 802DefineEngineMethod( GuiDecalEditorCtrl, setMode, void, ( String newMode ), , "setMode( String mode )()" ) 803{ 804 object->setMode( newMode ); 805} 806 807DefineEngineMethod( GuiDecalEditorCtrl, getMode, const char*, (), , "getMode()" ) 808{ 809 return object->mMode; 810} 811 812DefineEngineMethod( GuiDecalEditorCtrl, getDecalCount, S32, (), , "getDecalCount()" ) 813{ 814 return gDecalManager->mDecalInstanceVec.size(); 815} 816 817DefineEngineMethod( GuiDecalEditorCtrl, getDecalTransform, const char*, ( U32 id ), , "getDecalTransform()" ) 818{ 819 DecalInstance *decalInstance = gDecalManager->mDecalInstanceVec[id]; 820 821 if( decalInstance == NULL ) 822 return ""; 823 824 static const U32 bufSize = 256; 825 char* returnBuffer = Con::getReturnBuffer(bufSize); 826 returnBuffer[0] = 0; 827 828 if ( decalInstance ) 829 { 830 dSprintf(returnBuffer, bufSize, "%f %f %f %f %f %f %f", 831 decalInstance->mPosition.x, decalInstance->mPosition.y, decalInstance->mPosition.z, 832 decalInstance->mTangent.x, decalInstance->mTangent.y, decalInstance->mTangent.z, 833 decalInstance->mSize); 834 } 835 836 return returnBuffer; 837} 838 839DefineEngineMethod( GuiDecalEditorCtrl, getDecalLookupName, const char*, ( U32 id ), , "getDecalLookupName( S32 )()" ) 840{ 841 DecalInstance *decalInstance = gDecalManager->mDecalInstanceVec[id]; 842 if( decalInstance == NULL ) 843 return "invalid"; 844 845 return decalInstance->mDataBlock->lookupName; 846} 847 848DefineEngineMethod( GuiDecalEditorCtrl, selectDecal, void, ( U32 id ), , "selectDecal( S32 )()" ) 849{ 850 DecalInstance *decalInstance = gDecalManager->mDecalInstanceVec[id]; 851 if( decalInstance == NULL ) 852 return; 853 854 object->selectDecal( decalInstance ); 855} 856 857DefineEngineMethod( GuiDecalEditorCtrl, editDecalDetails, void, ( U32 id, Point3F pos, Point3F tan,F32 size ), , "editDecalDetails( S32 )()" ) 858{ 859 DecalInstance *decalInstance = gDecalManager->mDecalInstanceVec[id]; 860 if( decalInstance == NULL ) 861 return; 862 863 864 decalInstance->mPosition = pos; 865 decalInstance->mTangent = tan; 866 decalInstance->mSize = size; 867 868 if ( decalInstance == object->mSELDecal ) 869 object->setGizmoFocus( decalInstance ); 870 871 object->forceRedraw( decalInstance ); 872 873 gDecalManager->notifyDecalModified( decalInstance ); 874} 875 876DefineEngineMethod( GuiDecalEditorCtrl, getSelectionCount, S32, (), , "" ) 877{ 878 if ( object->mSELDecal != NULL ) 879 return 1; 880 return 0; 881} 882 883DefineEngineMethod( GuiDecalEditorCtrl, retargetDecalDatablock, void, ( const char * dbFrom, const char * dbTo ), , "" ) 884{ 885 if( String::compare( dbFrom, "" ) != 0 && String::compare( dbTo, "" ) != 0 ) 886 object->retargetDecalDatablock( dbFrom, dbTo ); 887} 888 889void GuiDecalEditorCtrl::setGizmoFocus( DecalInstance * decalInstance ) 890{ 891 const F32 &size = decalInstance->mSize; 892 MatrixF worldMat( true ); 893 decalInstance->getWorldMatrix( &worldMat, true ); 894 worldMat.setPosition( Point3F( 0, 0, 0 ) ); 895 mGizmo->set( worldMat, decalInstance->mPosition, Point3F( size, size, size ) ); 896} 897 898//Decal Instance Create Undo Actions 899IMPLEMENT_CONOBJECT( DICreateUndoAction ); 900 901ConsoleDocClass( DICreateUndoAction, 902 "@brief Decal Instance Create Undo Actions\n\n" 903 "Not intended for game development, for editors or internal use only.\n\n " 904 "@internal"); 905 906DICreateUndoAction::DICreateUndoAction( const UTF8* actionName ) 907 : UndoAction( actionName ), mEditor(0), mDatablockId(0) 908{ 909} 910 911DICreateUndoAction::~DICreateUndoAction() 912{ 913} 914 915void DICreateUndoAction::initPersistFields() 916{ 917 Parent::initPersistFields(); 918} 919 920void DICreateUndoAction::addDecal(const DecalInstance& decal) 921{ 922 mDecalInstance = decal; 923 mDatablockId = decal.mDataBlock->getId(); 924} 925 926void DICreateUndoAction::undo() 927{ 928 Vector<DecalInstance *>::iterator iter; 929 for(iter = gDecalManager->mDecalInstanceVec.begin();iter != gDecalManager->mDecalInstanceVec.end();iter++) 930 { 931 if( !(*iter) ) 932 continue; 933 934 if( (*iter)->mId != mDecalInstance.mId ) 935 continue; 936 937 if ( mEditor->isMethod( "onDeleteInstance" ) ) 938 { 939 char buffer[512]; 940 dSprintf(buffer, 512, "%i", (*iter)->mId); 941 Con::executef( mEditor, "onDeleteInstance", String(buffer).c_str(), (*iter)->mDataBlock->lookupName.c_str() ); 942 } 943 944 // Decal manager handles clearing the vector if the decal contains a valid id 945 if( mEditor->mSELDecal == (*iter) ) 946 mEditor->mSELDecal = NULL; 947 948 if( mEditor->mHLDecal == (*iter) ) 949 mEditor->mHLDecal = NULL; 950 951 gDecalManager->removeDecal( (*iter) ); 952 break; 953 } 954} 955 956void DICreateUndoAction::redo() 957{ 958 //Reinstate the valid datablock pointer 959 mDecalInstance.mDataBlock = dynamic_cast<DecalData *>( Sim::findObject( mDatablockId ) ); 960 961 DecalInstance * decal = gDecalManager->addDecal( mDecalInstance.mPosition, 962 mDecalInstance.mNormal, 963 mDecalInstance.mTangent, 964 mDecalInstance.mDataBlock, 965 ( mDecalInstance.mSize / mDecalInstance.mDataBlock->size ), 966 mDecalInstance.mTextureRectIdx, 967 mDecalInstance.mFlags ); 968 969 decal->mId = mDecalInstance.mId; 970 971 // Override the rectIdx regardless of random decision in addDecal 972 decal->mTextureRectIdx = mDecalInstance.mTextureRectIdx; 973 974 // We take care of filling in the vector space that was once there 975 gDecalManager->mDecalInstanceVec[decal->mId] = decal; 976 977 if ( mEditor->isMethod( "onCreateInstance" ) ) 978 { 979 char buffer[512]; 980 dSprintf(buffer, 512, "%i", decal->mId); 981 Con::executef( mEditor, "onCreateInstance", buffer, decal->mDataBlock->lookupName.c_str()); 982 } 983 mEditor->selectDecal( decal ); 984} 985 986//Decal Instance Delete Undo Actions 987IMPLEMENT_CONOBJECT( DIDeleteUndoAction ); 988 989ConsoleDocClass( DIDeleteUndoAction, 990 "@brief Decal Instance Delete Undo Actions\n\n" 991 "Not intended for game development, for editors or internal use only.\n\n " 992 "@internal"); 993 994DIDeleteUndoAction::DIDeleteUndoAction( const UTF8 *actionName ) 995 : UndoAction( actionName ), mEditor(0), mDatablockId(0) 996{ 997} 998 999DIDeleteUndoAction::~DIDeleteUndoAction() 1000{ 1001} 1002 1003void DIDeleteUndoAction::initPersistFields() 1004{ 1005 Parent::initPersistFields(); 1006} 1007 1008void DIDeleteUndoAction::deleteDecal(const DecalInstance& decal) 1009{ 1010 mDecalInstance = decal; 1011 mDatablockId = decal.mDataBlock->getId(); 1012} 1013 1014void DIDeleteUndoAction::undo() 1015{ 1016 //Reinstate the valid datablock pointer 1017 mDecalInstance.mDataBlock = dynamic_cast<DecalData *>( Sim::findObject( mDatablockId ) ); 1018 1019 DecalInstance * decal = gDecalManager->addDecal( mDecalInstance.mPosition, 1020 mDecalInstance.mNormal, 1021 mDecalInstance.mTangent, 1022 mDecalInstance.mDataBlock, 1023 ( mDecalInstance.mSize / mDecalInstance.mDataBlock->size ), 1024 mDecalInstance.mTextureRectIdx, 1025 mDecalInstance.mFlags ); 1026 1027 decal->mId = mDecalInstance.mId; 1028 1029 // Override the rectIdx regardless of random decision in addDecal 1030 decal->mTextureRectIdx = mDecalInstance.mTextureRectIdx; 1031 1032 // We take care of filling in the vector space that was once there 1033 gDecalManager->mDecalInstanceVec[decal->mId] = decal; 1034 1035 if ( mEditor->isMethod( "onCreateInstance" ) ) 1036 { 1037 char buffer[512]; 1038 dSprintf(buffer, 512, "%i", decal->mId); 1039 Con::executef( mEditor, "onCreateInstance", buffer, decal->mDataBlock->lookupName.c_str()); 1040 } 1041 mEditor->selectDecal( decal ); 1042} 1043 1044void DIDeleteUndoAction::redo() 1045{ 1046 Vector<DecalInstance *>::iterator iter; 1047 for(iter = gDecalManager->mDecalInstanceVec.begin();iter != gDecalManager->mDecalInstanceVec.end();iter++) 1048 { 1049 if( !(*iter) ) 1050 continue; 1051 1052 if( (*iter)->mId != mDecalInstance.mId ) 1053 continue; 1054 1055 if ( mEditor->isMethod( "onDeleteInstance" ) ) 1056 { 1057 char buffer[512]; 1058 dSprintf(buffer, 512, "%i", (*iter)->mId); 1059 Con::executef( mEditor, "onDeleteInstance", String(buffer).c_str(), (*iter)->mDataBlock->lookupName.c_str() ); 1060 } 1061 1062 // Decal manager handles clearing the vector if the decal contains a valid id 1063 if( mEditor->mSELDecal == (*iter) ) 1064 mEditor->mSELDecal = NULL; 1065 1066 if( mEditor->mHLDecal == (*iter) ) 1067 mEditor->mHLDecal = NULL; 1068 1069 gDecalManager->removeDecal( (*iter) ); 1070 break; 1071 } 1072} 1073 1074//Decal Datablock Delete Undo Actions 1075IMPLEMENT_CONOBJECT( DBDeleteUndoAction ); 1076 1077ConsoleDocClass( DBDeleteUndoAction, 1078 "@brief Decal Datablock Delete Undo Actions\n\n" 1079 "Not intended for game development, for editors or internal use only.\n\n " 1080 "@internal"); 1081 1082DBDeleteUndoAction::DBDeleteUndoAction( const UTF8 *actionName ) 1083 : UndoAction( actionName ), mEditor(0), mDatablockId(0) 1084{ 1085} 1086 1087DBDeleteUndoAction::~DBDeleteUndoAction() 1088{ 1089} 1090 1091void DBDeleteUndoAction::initPersistFields() 1092{ 1093 Parent::initPersistFields(); 1094} 1095 1096void DBDeleteUndoAction::deleteDecal(const DecalInstance& decal) 1097{ 1098 mDecalInstanceVec.increment(); 1099 mDecalInstanceVec.last() = decal; 1100} 1101 1102void DBDeleteUndoAction::undo() 1103{ 1104 DecalData * datablock = dynamic_cast<DecalData *>( Sim::findObject( mDatablockId ) ); 1105 if ( mEditor->isMethod( "undoDeleteDecalDatablock" ) ) 1106 Con::executef( mEditor, "undoDeleteDecalDatablock", datablock->lookupName.c_str()); 1107 1108 // Create and restore the decal instances 1109 for ( S32 i= mDecalInstanceVec.size()-1; i >= 0; i-- ) 1110 { 1111 DecalInstance vecInstance = mDecalInstanceVec[i]; 1112 1113 //Reinstate the valid datablock pointer 1114 vecInstance.mDataBlock = datablock; 1115 1116 DecalInstance * decalInstance = gDecalManager->addDecal( vecInstance.mPosition, 1117 vecInstance.mNormal, 1118 vecInstance.mTangent, 1119 vecInstance.mDataBlock, 1120 ( vecInstance.mSize / vecInstance.mDataBlock->size ), 1121 vecInstance.mTextureRectIdx, 1122 vecInstance.mFlags ); 1123 1124 decalInstance->mId = vecInstance.mId; 1125 1126 // Override the rectIdx regardless of random decision in addDecal 1127 decalInstance->mTextureRectIdx = vecInstance.mTextureRectIdx; 1128 1129 // We take care of filling in the vector space that was once there 1130 gDecalManager->mDecalInstanceVec[decalInstance->mId] = decalInstance; 1131 1132 if ( mEditor->isMethod( "onCreateInstance" ) ) 1133 { 1134 char buffer[512]; 1135 dSprintf(buffer, 512, "%i", decalInstance->mId); 1136 Con::executef( mEditor, "onCreateInstance", buffer, decalInstance->mDataBlock->lookupName.c_str()); 1137 } 1138 } 1139 1140} 1141 1142void DBDeleteUndoAction::redo() 1143{ 1144 for ( S32 i=0; i < mDecalInstanceVec.size(); i++ ) 1145 { 1146 DecalInstance vecInstance = mDecalInstanceVec[i]; 1147 1148 Vector<DecalInstance *>::iterator iter; 1149 for(iter = gDecalManager->mDecalInstanceVec.begin();iter != gDecalManager->mDecalInstanceVec.end();iter++) 1150 { 1151 DecalInstance * decalInstance = (*iter); 1152 if( !decalInstance ) 1153 continue; 1154 1155 if( decalInstance->mId != vecInstance.mId ) 1156 continue; 1157 1158 if ( mEditor->isMethod( "onDeleteInstance" ) ) 1159 { 1160 char buffer[512]; 1161 dSprintf(buffer, 512, "%i", decalInstance->mId); 1162 Con::executef( mEditor, "onDeleteInstance", String(buffer).c_str(), decalInstance->mDataBlock->lookupName.c_str() ); 1163 } 1164 1165 // Decal manager handles clearing the vector if the decal contains a valid id 1166 if( mEditor->mSELDecal == decalInstance ) 1167 mEditor->mSELDecal = NULL; 1168 1169 if( mEditor->mHLDecal == decalInstance ) 1170 mEditor->mHLDecal = NULL; 1171 1172 gDecalManager->removeDecal( decalInstance ); 1173 break; 1174 } 1175 } 1176 1177 DecalData * datablock = dynamic_cast<DecalData *>( Sim::findObject( mDatablockId ) ); 1178 if ( mEditor->isMethod( "redoDeleteDecalDatablock" ) ) 1179 Con::executef( mEditor, "redoDeleteDecalDatablock", datablock->lookupName.c_str()); 1180} 1181 1182//------------------------------ 1183//Decal Datablock Retarget Undo Actions 1184IMPLEMENT_CONOBJECT( DBRetargetUndoAction ); 1185 1186ConsoleDocClass( DBRetargetUndoAction, 1187 "@brief Decal Datablock Retarget Undo Actions\n\n" 1188 "Not intended for game development, for editors or internal use only.\n\n " 1189 "@internal"); 1190 1191DBRetargetUndoAction::DBRetargetUndoAction( const UTF8 *actionName ) 1192 : UndoAction( actionName ), mEditor(0), mDBFromId(0), mDBToId(0) 1193{ 1194} 1195 1196DBRetargetUndoAction::~DBRetargetUndoAction() 1197{ 1198} 1199 1200void DBRetargetUndoAction::initPersistFields() 1201{ 1202 Parent::initPersistFields(); 1203} 1204 1205void DBRetargetUndoAction::retargetDecal( DecalInstance* decal ) 1206{ 1207 mDecalInstanceVec.increment(); 1208 mDecalInstanceVec.last() = decal; 1209} 1210 1211void DBRetargetUndoAction::undo() 1212{ 1213 DecalData * ptrFrom = dynamic_cast<DecalData*> ( Sim::findObject(mDBFromId) ); 1214 1215 if( !ptrFrom ) 1216 return; 1217 1218 Vector<DecalInstance *>::iterator iter; 1219 for(iter = mDecalInstanceVec.begin();iter != mDecalInstanceVec.end();iter++) 1220 { 1221 (*iter)->mDataBlock = ptrFrom; 1222 mEditor->forceRedraw((*iter)); 1223 } 1224 if ( mEditor->isMethod( "rebuildInstanceTree" ) ) 1225 Con::executef( mEditor, "rebuildInstanceTree" ); 1226} 1227 1228void DBRetargetUndoAction::redo() 1229{ 1230 DecalData * ptrTo = dynamic_cast<DecalData*> ( Sim::findObject(mDBToId) ); 1231 1232 if( !ptrTo ) 1233 return; 1234 1235 Vector<DecalInstance *>::iterator iter; 1236 for(iter = mDecalInstanceVec.begin();iter != mDecalInstanceVec.end();iter++) 1237 { 1238 (*iter)->mDataBlock = ptrTo; 1239 mEditor->forceRedraw((*iter)); 1240 } 1241 1242 if ( mEditor->isMethod( "rebuildInstanceTree" ) ) 1243 Con::executef( mEditor, "rebuildInstanceTree" ); 1244} 1245#endif 1246